From d2ad48379ce2ff238a53a96e92ec9a4d1980fd2e Mon Sep 17 00:00:00 2001 From: tallicamike Date: Thu, 7 Aug 2014 14:50:04 +0300 Subject: [PATCH 1/3] check validity for to/from in sipmsg_validate --- modules/sipmsgops/README | 8 +++ modules/sipmsgops/doc/sipmsgops_admin.xml | 14 +++++ modules/sipmsgops/sipmsgops.c | 71 +++++++++++++++++++++++ 3 files changed, 93 insertions(+) diff --git a/modules/sipmsgops/README b/modules/sipmsgops/README index c86d420fa24..d2fa36d29f1 100644 --- a/modules/sipmsgops/README +++ b/modules/sipmsgops/README @@ -516,6 +516,10 @@ add_body("Hello World!", "text/plain"); * 'm' - don't check the Max-Forwards header. * 'r' - checks the R-URI and whether the domain contains valid characters. + * 'f' - checks the URI of the 'From' field and whether the + domain contains valid characters. + * 't' - checks the URI of the 'To' field and whether the + domain contains valid characters. The result_pvar parameter sets resulting pvar with text error reason in case of negative result ( easy for logging or @@ -547,6 +551,10 @@ add_body("Hello World!", "text/plain"); * -19 - No Unsupported header in 420 reply. * -20 - No WWW-Authorize header in 401 reply. * -21 - No Content-Type header + * -22 - To header parse error + * -23 - From header parse error + * -24 - Bad hostname in To header + * -25 - Bad hostname in From header * -255 - undefined errors. This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE, diff --git a/modules/sipmsgops/doc/sipmsgops_admin.xml b/modules/sipmsgops/doc/sipmsgops_admin.xml index 7cd3465e8f6..dee74f07935 100644 --- a/modules/sipmsgops/doc/sipmsgops_admin.xml +++ b/modules/sipmsgops/doc/sipmsgops_admin.xml @@ -722,6 +722,12 @@ add_body("Hello World!", "text/plain"); 'r' - checks the R-URI and whether the domain contains valid characters. + 'f' - checks the URI of the 'From' field + and whether the domain contains valid characters. + + 't' - checks the URI of the 'To' field + and whether the domain contains valid characters. + The result_pvar parameter sets resulting pvar with text error reason in case of @@ -775,6 +781,14 @@ add_body("Hello World!", "text/plain"); -21 - No Content-Type header + -22 - To header parse error + + -23 - From header parse error + + -24 - Bad hostname in To header + + -25 - Bad hostname in From header + -255 - undefined errors. diff --git a/modules/sipmsgops/sipmsgops.c b/modules/sipmsgops/sipmsgops.c index bae9be0c9d4..033e83c2ab1 100644 --- a/modules/sipmsgops/sipmsgops.c +++ b/modules/sipmsgops/sipmsgops.c @@ -1413,6 +1413,8 @@ static int is_audio_on_hold_f(struct sip_msg *msg, char *str1, char *str2 ) #define SIP_PARSE_HDR 0x2 #define SIP_PARSE_NOMF 0x4 #define SIP_PARSE_RURI 0x8 +#define SIP_PARSE_TO 0x10 +#define SIP_PARSE_FROM 0x20 static int fixup_sip_validate(void** param, int param_no) { @@ -1450,6 +1452,16 @@ static int fixup_sip_validate(void** param, int param_no) flags |= SIP_PARSE_RURI; break; + case 't': + case 'T': + flags |= SIP_PARSE_TO; + break; + + case 'f': + case 'F': + flags |= SIP_PARSE_FROM; + break; + default: LM_DBG("unknown option \'%c\'\n", *flags_s); break; @@ -1796,6 +1808,10 @@ enum sip_validation_failures { SV_NO_UNSUPPORTED=-19, SV_NO_WWW_AUTH=-20, SV_NO_CONTENT_TYPE=-21, + SV_TO_PARSE_ERROR=-22, + SV_FROM_PARSE_ERROR=-23, + SV_TO_DOMAIN_ERROR=-24, + SV_FROM_DOMAIN_ERROR=-25, SV_GENERIC_FAILURE=-255 }; @@ -1805,6 +1821,7 @@ static int w_sip_validate(struct sip_msg *msg, char *flags_s, char* pv_result) int method; str body; struct cseq_body * cbody; + struct to_body *from, *to; unsigned long flags; pv_elem_t* pv_res = (pv_elem_t*)pv_result; pv_value_t pv_val; @@ -1905,6 +1922,60 @@ static int w_sip_validate(struct sip_msg *msg, char *flags_s, char* pv_result) /* check only if Via1 is present */ ret = SV_NO_VIA1; CHECK_HEADER("", via1); + + /* test to header uri */ + if(flags & SIP_PARSE_TO) { + if(!msg->to->parsed) { + if(parse_to_header(msg) < 0) { + strcpy(reason, "failed to parse \'To\' field URI"); + ret = SV_TO_PARSE_ERROR; + goto failed; + } + } + + to = (struct to_body*)msg->to->parsed; + + if(to->error == PARSE_ERROR || + parse_uri(to->uri.s, to->uri.len, &to->parsed_uri) < 0) { + strcpy(reason, "failed to parse \'To\' field URI"); + ret = SV_TO_PARSE_ERROR; + goto failed; + } + + /* check for valid domain format */ + if(check_hostname(&to->parsed_uri.host) < 0) { + strcpy(reason, "invalid domain for \'To\' field"); + ret = SV_TO_DOMAIN_ERROR; + goto failed; + } + } + + /* test from header uri */ + if(flags & SIP_PARSE_FROM) { + if(!msg->from->parsed) { + if(parse_from_header(msg) < 0) { + strcpy(reason, "failed to parse \'From\' field URI"); + ret = SV_FROM_PARSE_ERROR; + goto failed; + } + } + + from = (struct to_body*)msg->from->parsed; + + if(from->error == PARSE_ERROR || + parse_uri(from->uri.s, from->uri.len, &from->parsed_uri) < 0) { + strcpy(reason, "failed to parse \'From\' field URI"); + ret = SV_FROM_PARSE_ERROR; + goto failed; + } + + /* check for valid domain format */ + if(check_hostname(&from->parsed_uri.host) < 0) { + strcpy(reason, "invalid domain for \'From\' field"); + ret = SV_FROM_DOMAIN_ERROR; + goto failed; + } + } /* request or reply */ switch (msg->first_line.type) { From f8e210e86e22d1f1e4212fa2a4d4af696e01f67e Mon Sep 17 00:00:00 2001 From: tallicamike Date: Fri, 8 Aug 2014 16:02:19 +0300 Subject: [PATCH 2/3] sanity check for contact header(s) --- modules/sipmsgops/README | 2 + modules/sipmsgops/doc/sipmsgops_admin.xml | 4 + modules/sipmsgops/sipmsgops.c | 388 ++++++++++++---------- 3 files changed, 219 insertions(+), 175 deletions(-) diff --git a/modules/sipmsgops/README b/modules/sipmsgops/README index d2fa36d29f1..61c9147e980 100644 --- a/modules/sipmsgops/README +++ b/modules/sipmsgops/README @@ -520,6 +520,7 @@ add_body("Hello World!", "text/plain"); domain contains valid characters. * 't' - checks the URI of the 'To' field and whether the domain contains valid characters. + * 'c' - checks the URI of the 'Contact' field. The result_pvar parameter sets resulting pvar with text error reason in case of negative result ( easy for logging or @@ -555,6 +556,7 @@ add_body("Hello World!", "text/plain"); * -23 - From header parse error * -24 - Bad hostname in To header * -25 - Bad hostname in From header + * -26 - Contact header parse error * -255 - undefined errors. This function can be used from REQUEST_ROUTE, ONREPLY_ROUTE, diff --git a/modules/sipmsgops/doc/sipmsgops_admin.xml b/modules/sipmsgops/doc/sipmsgops_admin.xml index dee74f07935..2ffd7c58523 100644 --- a/modules/sipmsgops/doc/sipmsgops_admin.xml +++ b/modules/sipmsgops/doc/sipmsgops_admin.xml @@ -728,6 +728,8 @@ add_body("Hello World!", "text/plain"); 't' - checks the URI of the 'To' field and whether the domain contains valid characters. + 'c' - checks the URI of the 'Contact' field. + The result_pvar parameter sets resulting pvar with text error reason in case of @@ -789,6 +791,8 @@ add_body("Hello World!", "text/plain"); -25 - Bad hostname in From header + -26 - Contact header parse error + -255 - undefined errors. diff --git a/modules/sipmsgops/sipmsgops.c b/modules/sipmsgops/sipmsgops.c index 033e83c2ab1..3497c8d5ae5 100644 --- a/modules/sipmsgops/sipmsgops.c +++ b/modules/sipmsgops/sipmsgops.c @@ -1415,6 +1415,7 @@ static int is_audio_on_hold_f(struct sip_msg *msg, char *str1, char *str2 ) #define SIP_PARSE_RURI 0x8 #define SIP_PARSE_TO 0x10 #define SIP_PARSE_FROM 0x20 +#define SIP_PARSE_CONTACT 0x40 static int fixup_sip_validate(void** param, int param_no) { @@ -1460,6 +1461,11 @@ static int fixup_sip_validate(void** param, int param_no) case 'f': case 'F': flags |= SIP_PARSE_FROM; + break; + + case 'c': + case 'C': + flags |= SIP_PARSE_CONTACT; break; default: @@ -1809,9 +1815,10 @@ enum sip_validation_failures { SV_NO_WWW_AUTH=-20, SV_NO_CONTENT_TYPE=-21, SV_TO_PARSE_ERROR=-22, - SV_FROM_PARSE_ERROR=-23, - SV_TO_DOMAIN_ERROR=-24, + SV_TO_DOMAIN_ERROR=-23, + SV_FROM_PARSE_ERROR=-24, SV_FROM_DOMAIN_ERROR=-25, + SV_CONTACT_PARSE_ERROR=-26, SV_GENERIC_FAILURE=-255 }; @@ -1820,8 +1827,11 @@ static int w_sip_validate(struct sip_msg *msg, char *flags_s, char* pv_result) unsigned int hdrs_len; int method; str body; + struct hdr_field * ptr; + contact_t * contacts; + struct sip_uri test_contacts; struct cseq_body * cbody; - struct to_body *from, *to; + struct to_body *from, *to; unsigned long flags; pv_elem_t* pv_res = (pv_elem_t*)pv_result; pv_value_t pv_val; @@ -1927,7 +1937,7 @@ static int w_sip_validate(struct sip_msg *msg, char *flags_s, char* pv_result) if(flags & SIP_PARSE_TO) { if(!msg->to->parsed) { if(parse_to_header(msg) < 0) { - strcpy(reason, "failed to parse \'To\' field URI"); + strcpy(reason, "failed to parse \'To\' header"); ret = SV_TO_PARSE_ERROR; goto failed; } @@ -1935,16 +1945,15 @@ static int w_sip_validate(struct sip_msg *msg, char *flags_s, char* pv_result) to = (struct to_body*)msg->to->parsed; - if(to->error == PARSE_ERROR || - parse_uri(to->uri.s, to->uri.len, &to->parsed_uri) < 0) { - strcpy(reason, "failed to parse \'To\' field URI"); + if(parse_uri(to->uri.s, to->uri.len, &to->parsed_uri) < 0) { + strcpy(reason, "failed to parse \'To\' header"); ret = SV_TO_PARSE_ERROR; goto failed; } /* check for valid domain format */ if(check_hostname(&to->parsed_uri.host) < 0) { - strcpy(reason, "invalid domain for \'To\' field"); + strcpy(reason, "invalid domain for \'To\' header"); ret = SV_TO_DOMAIN_ERROR; goto failed; } @@ -1954,7 +1963,7 @@ static int w_sip_validate(struct sip_msg *msg, char *flags_s, char* pv_result) if(flags & SIP_PARSE_FROM) { if(!msg->from->parsed) { if(parse_from_header(msg) < 0) { - strcpy(reason, "failed to parse \'From\' field URI"); + strcpy(reason, "failed to parse \'From\' header"); ret = SV_FROM_PARSE_ERROR; goto failed; } @@ -1962,16 +1971,15 @@ static int w_sip_validate(struct sip_msg *msg, char *flags_s, char* pv_result) from = (struct to_body*)msg->from->parsed; - if(from->error == PARSE_ERROR || - parse_uri(from->uri.s, from->uri.len, &from->parsed_uri) < 0) { - strcpy(reason, "failed to parse \'From\' field URI"); + if(parse_uri(from->uri.s, from->uri.len, &from->parsed_uri) < 0) { + strcpy(reason, "failed to parse \'From\' header"); ret = SV_FROM_PARSE_ERROR; goto failed; } /* check for valid domain format */ if(check_hostname(&from->parsed_uri.host) < 0) { - strcpy(reason, "invalid domain for \'From\' field"); + strcpy(reason, "invalid domain for \'From\' header"); ret = SV_FROM_DOMAIN_ERROR; goto failed; } @@ -1989,7 +1997,7 @@ static int w_sip_validate(struct sip_msg *msg, char *flags_s, char* pv_result) goto failed; } if (check_hostname(&msg->parsed_uri.host) < 0) { - strcpy(reason, "invalid domain"); + strcpy(reason, "invalid domain for R-URI"); ret = SV_BAD_HOSTNAME; goto failed; } @@ -2003,124 +2011,154 @@ static int w_sip_validate(struct sip_msg *msg, char *flags_s, char* pv_result) if (msg->REQ_METHOD == METHOD_INVITE) { ret = SV_NO_CONTACT; CHECK_HEADER("INVITE", contact); - } - - if (msg->REQ_METHOD != METHOD_REGISTER && msg->path) { - strcpy(reason, "PATH header supported only for REGISTERs"); - ret = SV_PATH_NONREGISTER; - goto failed; - } - - method = msg->REQ_METHOD; - - break; - - case SIP_REPLY: - /* checking the reply's message type */ - cbody = (struct cseq_body *)msg->cseq->parsed; - if (!cbody) { - strcpy(reason, "cseq not parsed properly"); - ret = SV_NO_CSEQ; - goto failed; - } - method = cbody->method_id; - if (method != METHOD_CANCEL) { - switch (msg->first_line.u.reply.statuscode) { - case 405: - ret = SV_NOALLOW_405; - CHECK_HEADER("", allow); - break; + if(flags & SIP_PARSE_CONTACT) { + /* iterate through Contact headers */ + for(ptr = msg->contact; ptr; ptr = ptr->sibling) { + /* parse Contact header */ + if(!ptr->parsed && (parse_contact(ptr) < 0 + || !ptr->parsed)) { + strcpy(reason, "failed to parse \'Contact\' header"); + ret = SV_CONTACT_PARSE_ERROR; + goto failed; + } + contacts = ((contact_body_t*)ptr->parsed)->contacts; + /* empty contacts header - something must be wrong */ + if(contacts == NULL) { + strcpy(reason, "emtpy body for \'Contact\' header"); + ret = SV_CONTACT_PARSE_ERROR; + goto failed; + } + /* iterate through URIs and check validty */ + for(; contacts; contacts = contacts->next) { + if(parse_uri(contacts->uri.s, contacts->uri.len, + &test_contacts) < 0 + || test_contacts.host.len < 0) { + strcpy(reason, "failed to parse \'Contact\' header"); + ret = SV_CONTACT_PARSE_ERROR; + goto failed; + } + } + } + + } + } - case 423: - if (method == METHOD_REGISTER) { - ret = SV_NOMINEXP_423; - CHECK_HEADER("REGISTER", min_expires); - } - break; + if (msg->REQ_METHOD != METHOD_REGISTER && msg->path) { + strcpy(reason, "PATH header supported only for REGISTERs"); + ret = SV_PATH_NONREGISTER; + goto failed; + } - case 407: - ret = SV_NO_PROXY_AUTH; - CHECK_HEADER("", proxy_authenticate); - break; + method = msg->REQ_METHOD; - case 420: - ret = SV_NO_UNSUPPORTED; - CHECK_HEADER("", unsupported); - break; + break; - case 401: - ret = SV_NO_WWW_AUTH; - CHECK_HEADER("", www_authenticate); - break; - } - } + case SIP_REPLY: + /* checking the reply's message type */ + cbody = (struct cseq_body *)msg->cseq->parsed; + if (!cbody) { + strcpy(reason, "cseq not parsed properly"); + ret = SV_NO_CSEQ; + goto failed; + } + method = cbody->method_id; + if (method != METHOD_CANCEL) { + switch (msg->first_line.u.reply.statuscode) { + case 405: + ret = SV_NOALLOW_405; + CHECK_HEADER("", allow); + break; + + case 423: + if (method == METHOD_REGISTER) { + ret = SV_NOMINEXP_423; + CHECK_HEADER("REGISTER", min_expires); + } + break; + + case 407: + ret = SV_NO_PROXY_AUTH; + CHECK_HEADER("", proxy_authenticate); + break; + + case 420: + ret = SV_NO_UNSUPPORTED; + CHECK_HEADER("", unsupported); + break; + + case 401: + ret = SV_NO_WWW_AUTH; + CHECK_HEADER("", www_authenticate); + break; + } + } - break; + break; - default: - strcpy(reason, "invalid message type"); - ret = SV_GENERIC_FAILURE; - goto failed; - } - /* check for body */ - if (method != METHOD_CANCEL) { - if (!msg->unparsed) { - strcpy(reason, "invalid parsing"); - ret = SV_HDR_PARSE_ERROR; - goto failed; - } - hdrs_len=(unsigned int)(msg->unparsed-msg->buf); + default: + strcpy(reason, "invalid message type"); + ret = SV_GENERIC_FAILURE; + goto failed; + } + /* check for body */ + if (method != METHOD_CANCEL) { + if (!msg->unparsed) { + strcpy(reason, "invalid parsing"); + ret = SV_HDR_PARSE_ERROR; + goto failed; + } + hdrs_len=(unsigned int)(msg->unparsed-msg->buf); + + if ((hdrs_len+2<=msg->len) && (strncmp(CRLF,msg->unparsed,CRLF_LEN)==0) ) + body.s = msg->unparsed + CRLF_LEN; + else if ( (hdrs_len+1<=msg->len) && + (*(msg->unparsed)=='\n' || *(msg->unparsed)=='\r' ) ) + body.s = msg->unparsed + 1; + else { + /* no body */ + body.s = NULL; + body.len = 0; + } - if ((hdrs_len+2<=msg->len) && (strncmp(CRLF,msg->unparsed,CRLF_LEN)==0) ) - body.s = msg->unparsed + CRLF_LEN; - else if ( (hdrs_len+1<=msg->len) && - (*(msg->unparsed)=='\n' || *(msg->unparsed)=='\r' ) ) - body.s = msg->unparsed + 1; - else { - /* no body */ - body.s = NULL; - body.len = 0; - } + /* determine the length of the body */ + body.len = msg->buf + msg->len - body.s; - /* determine the length of the body */ - body.len = msg->buf + msg->len - body.s; - - if (get_content_length(msg) != body.len) { - snprintf(reason, MAX_REASON-1, "invalid body - content length %ld different then " - "actual body %d\n", get_content_length(msg), body.len); - ret = SV_INVALID_CONTENT_LENGTH; - goto failed; - } + if (get_content_length(msg) != body.len) { + snprintf(reason, MAX_REASON-1, "invalid body - content length %ld different then " + "actual body %d\n", get_content_length(msg), body.len); + ret = SV_INVALID_CONTENT_LENGTH; + goto failed; + } - if (body.len && body.s) { - /* if it really has body, check for content type */ - ret = SV_NO_CONTENT_TYPE; - CHECK_HEADER("", content_type); - } - } + if (body.len && body.s) { + /* if it really has body, check for content type */ + ret = SV_NO_CONTENT_TYPE; + CHECK_HEADER("", content_type); + } + } - if ((flags & SIP_PARSE_HDR) && sip_validate_hdrs(msg) < 0) { - strcpy(reason, "failed to parse headers"); - ret = SV_HDR_PARSE_ERROR; - goto failed; - } + if ((flags & SIP_PARSE_HDR) && sip_validate_hdrs(msg) < 0) { + strcpy(reason, "failed to parse headers"); + ret = SV_HDR_PARSE_ERROR; + goto failed; + } - return 1; + return 1; failed: - LM_DBG("message does not comply with SIP RFC3261 : (%s)\n", reason); - - if (pv_result != NULL) - { - pv_val.rs.len = strlen(reason); - pv_val.rs.s = reason; - pv_val.flags = PV_VAL_STR; - if (pv_set_value(msg, &pv_res->spec, 0, &pv_val) != 0) - { - LM_ERR("cannot populate parameter\n"); - return SV_GENERIC_FAILURE; - } - } - return ret; + LM_DBG("message does not comply with SIP RFC3261 : (%s)\n", reason); + + if (pv_result != NULL) + { + pv_val.rs.len = strlen(reason); + pv_val.rs.s = reason; + pv_val.flags = PV_VAL_STR; + if (pv_set_value(msg, &pv_res->spec, 0, &pv_val) != 0) + { + LM_ERR("cannot populate parameter\n"); + return SV_GENERIC_FAILURE; + } + } + return ret; } #undef CHECK_HEADER @@ -2130,73 +2168,73 @@ static int w_sip_validate(struct sip_msg *msg, char *flags_s, char* pv_result) /* Change_reply_status config parsing function (supports AVPs) */ static int change_reply_status_fixup(void** param, int param_no) { - if(param_no == 1) - return fixup_igp(param); + if(param_no == 1) + return fixup_igp(param); - if(param_no == 2) - return fixup_spve(param); + if(param_no == 2) + return fixup_spve(param); - return 0; + return 0; } /* Function to change the reply status in reply route */ static int change_reply_status_f(struct sip_msg* msg, char* str1, char* str2) { - int code_i; - str code_s; - struct lump *l; - char *ch; - - if(fixup_get_ivalue(msg, (gparam_p)str1, &code_i) < 0) { - LM_ERR("Wrong param 1, expected integer\n"); - return -1; - } - - if ( fixup_get_svalue(msg, (gparam_p) str2, &code_s) < 0) { - LM_ERR("Wrong param 2, expected string\n"); - return -1; - } + int code_i; + str code_s; + struct lump *l; + char *ch; + + if(fixup_get_ivalue(msg, (gparam_p)str1, &code_i) < 0) { + LM_ERR("Wrong param 1, expected integer\n"); + return -1; + } - if ((code_i < 100) || (code_i > 699)) { - LM_ERR("wrong status code: %d\n", code_i); - return -1; - } + if ( fixup_get_svalue(msg, (gparam_p) str2, &code_s) < 0) { + LM_ERR("Wrong param 2, expected string\n"); + return -1; + } - if (((code_i < 300) || (msg->REPLY_STATUS < 300)) - && (code_i/100 != msg->REPLY_STATUS/100)) { - LM_ERR("the class of provisional or positive final replies" - " cannot be changed\n"); - return -1; - } + if ((code_i < 100) || (code_i > 699)) { + LM_ERR("wrong status code: %d\n", code_i); + return -1; + } - /* rewrite the status code directly in the message buffer */ - msg->first_line.u.reply.statuscode = code_i; - msg->first_line.u.reply.status.s[2] = code_i % 10 + '0'; code_i /= 10; - msg->first_line.u.reply.status.s[1] = code_i % 10 + '0'; code_i /= 10; - msg->first_line.u.reply.status.s[0] = code_i + '0'; + if (((code_i < 300) || (msg->REPLY_STATUS < 300)) + && (code_i/100 != msg->REPLY_STATUS/100)) { + LM_ERR("the class of provisional or positive final replies" + " cannot be changed\n"); + return -1; + } - l = del_lump(msg, - msg->first_line.u.reply.reason.s - msg->buf, - msg->first_line.u.reply.reason.len, - 0); - if (!l) { - LM_ERR("Failed to add del lump\n"); - return -1; - } - /* clone the reason phrase, the lumps need to be pkg allocated */ - ch = (char *)pkg_malloc(code_s.len); - if (!ch) { - LM_ERR("Not enough memory\n"); - return -1; - } + /* rewrite the status code directly in the message buffer */ + msg->first_line.u.reply.statuscode = code_i; + msg->first_line.u.reply.status.s[2] = code_i % 10 + '0'; code_i /= 10; + msg->first_line.u.reply.status.s[1] = code_i % 10 + '0'; code_i /= 10; + msg->first_line.u.reply.status.s[0] = code_i + '0'; + + l = del_lump(msg, + msg->first_line.u.reply.reason.s - msg->buf, + msg->first_line.u.reply.reason.len, + 0); + if (!l) { + LM_ERR("Failed to add del lump\n"); + return -1; + } + /* clone the reason phrase, the lumps need to be pkg allocated */ + ch = (char *)pkg_malloc(code_s.len); + if (!ch) { + LM_ERR("Not enough memory\n"); + return -1; + } - memcpy(ch, code_s.s, code_s.len); - if (insert_new_lump_after(l, ch, code_s.len, 0)==0){ - LM_ERR("failed to add new lump: %.*s\n", code_s.len, ch); - pkg_free(ch); - return -1; - } + memcpy(ch, code_s.s, code_s.len); + if (insert_new_lump_after(l, ch, code_s.len, 0)==0){ + LM_ERR("failed to add new lump: %.*s\n", code_s.len, ch); + pkg_free(ch); + return -1; + } - return 1; + return 1; } From e4b080f3e2e5ce197e1ffa215e0e09b4a705c348 Mon Sep 17 00:00:00 2001 From: tallicamike Date: Mon, 11 Aug 2014 12:45:40 +0300 Subject: [PATCH 3/3] indentation with tabs, correct typos, remove escaped quotes. thank you Walter Doekes for the code review. --- modules/sipmsgops/sipmsgops.c | 870 +++++++++++++++++----------------- 1 file changed, 435 insertions(+), 435 deletions(-) diff --git a/modules/sipmsgops/sipmsgops.c b/modules/sipmsgops/sipmsgops.c index 3497c8d5ae5..a6eb73c58bd 100644 --- a/modules/sipmsgops/sipmsgops.c +++ b/modules/sipmsgops/sipmsgops.c @@ -102,7 +102,7 @@ static str header_body = {0, 0}; %a -- abbreviated week of day name (locale), %d day of month as decimal number, %b abbreviated month name (locale), %Y year with century, %T time in 24h notation -*/ + */ #define TIME_FORMAT "Date: %a, %d %b %Y %H:%M:%S GMT" #define MAX_TIME 64 @@ -292,40 +292,40 @@ static int mod_init(void) } static inline int find_line_start(char *text, unsigned int text_len, - char **buf, unsigned int *buf_len) + char **buf, unsigned int *buf_len) { - char *ch, *start; - unsigned int len; + char *ch, *start; + unsigned int len; - start = *buf; - len = *buf_len; + start = *buf; + len = *buf_len; - while (text_len <= len) { - if (strncmp(text, start, text_len) == 0) { - *buf = start; - *buf_len = len; - return 1; - } - if ((ch = memchr(start, 13, len - 1))) { - if (*(ch + 1) != 10) { - LM_ERR("No LF after CR\n"); - return 0; - } - len = len - (ch - start + 2); - start = ch + 2; - } else { - LM_ERR("No CRLF found\n"); - return 0; + while (text_len <= len) { + if (strncmp(text, start, text_len) == 0) { + *buf = start; + *buf_len = len; + return 1; + } + if ((ch = memchr(start, 13, len - 1))) { + if (*(ch + 1) != 10) { + LM_ERR("No LF after CR\n"); + return 0; + } + len = len - (ch - start + 2); + start = ch + 2; + } else { + LM_ERR("No CRLF found\n"); + return 0; + } } - } - return 0; + return 0; } /* Filters multipart body by leaving out everything else except * first body part of given content type. */ static int filter_body_f(struct sip_msg* msg, char* _content_type, - char* ignored) + char* ignored) { char *start; unsigned int len; @@ -341,47 +341,47 @@ static int filter_body_f(struct sip_msg* msg, char* _content_type, len = body.len; while (find_line_start("Content-Type: ", 14, &start, &len)) { - start = start + 14; - len = len - 14; - if (len > content_type->len + 2) { - if (strncasecmp(start, content_type->s, content_type->len) - == 0) { - start = start + content_type->len; - len = len - content_type->len; - if ((*start != 13) || (*(start + 1) != 10)) { - LM_ERR("No CRLF found after content type\n"); - return -1; - } - while ((len > 3) && !(*start == 13 && *(start+1) == 10 && *(start+2) == 13 && *(start+3) == 10)) { - len = len - 1; - start = start + 1; - } - while ((len > 0) && ((*start == 13) || (*start == 10))) { - len = len - 1; - start = start + 1; - } - if (del_lump(msg, body.s - msg->buf, start - body.s, 0) - == 0) { - LM_ERR("Deleting lump <%.*s> failed\n", - (int)(start - body.s), body.s); - return -1; - } - if (find_line_start("--Boundary", 10, &start, &len)) { - if (del_lump(msg, start - msg->buf, len, 0) == 0) { - LM_ERR("Deleting lump <%.*s> failed\n", - len, start); - return -1; - } else { - return 1; + start = start + 14; + len = len - 14; + if (len > content_type->len + 2) { + if (strncasecmp(start, content_type->s, content_type->len) + == 0) { + start = start + content_type->len; + len = len - content_type->len; + if ((*start != 13) || (*(start + 1) != 10)) { + LM_ERR("No CRLF found after content type\n"); + return -1; + } + while ((len > 3) && !(*start == 13 && *(start+1) == 10 && *(start+2) == 13 && *(start+3) == 10)) { + len = len - 1; + start = start + 1; + } + while ((len > 0) && ((*start == 13) || (*start == 10))) { + len = len - 1; + start = start + 1; + } + if (del_lump(msg, body.s - msg->buf, start - body.s, 0) + == 0) { + LM_ERR("Deleting lump <%.*s> failed\n", + (int)(start - body.s), body.s); + return -1; + } + if (find_line_start("--Boundary", 10, &start, &len)) { + if (del_lump(msg, start - msg->buf, len, 0) == 0) { + LM_ERR("Deleting lump <%.*s> failed\n", + len, start); + return -1; + } else { + return 1; + } + } else { + LM_ERR("Boundary not found after content\n"); + return -1; + } } - } else { - LM_ERR("Boundary not found after content\n"); + } else { return -1; - } } - } else { - return -1; - } } return -1; } @@ -416,7 +416,7 @@ int parse_pvs_header(struct sip_msg *msg, gparam_p gp) LM_DBG("Parsing %.*s\n", hdr_len, header_body.s); if (parse_hname2(header_body.s, header_body.s + - (hdr_len < 4 ? 4 : hdr_len), &hdr) == 0) + (hdr_len < 4 ? 4 : hdr_len), &hdr) == 0) { LM_ERR("error parsing header name\n"); pkg_free(gp); @@ -447,7 +447,7 @@ static int hf_already_removed(struct sip_msg* msg, unsigned int offset, /* parse only the msg headers, not the body */ for (it = msg->add_rm; it; it = it->next) { if (it->op == LUMP_DEL && it->type == type && - it->u.offset == offset && it->len == len) + it->u.offset == offset && it->len == len) return 1; } return 0; @@ -464,7 +464,7 @@ static int remove_hf_f(struct sip_msg* msg, char* str_hf, char* foo) cnt=0; if (gp->type == GPARAM_TYPE_PVS && - parse_pvs_header(msg, gp) != 0) + parse_pvs_header(msg, gp) != 0) { LM_ERR("Parse pvs header failed!\n"); return -1; @@ -490,7 +490,7 @@ static int remove_hf_f(struct sip_msg* msg, char* str_hf, char* foo) } /* check to see if the header was already removed */ if (hf_already_removed(msg, hf->name.s-msg->buf, hf->len, - hf->type)) + hf->type)) continue; l=del_lump(msg, hf->name.s-msg->buf, hf->len, hf->type); if (l==0) { @@ -522,34 +522,34 @@ static int remove_hf_match_f(struct sip_msg* msg, char* pattern, char* regex_or_ return -1; } for (hf=msg->headers; hf; hf=hf->next) { - tmp = *(hf->name.s+hf->name.len); - *(hf->name.s+hf->name.len) = 0; - if( matchtype == 'g' ) { /* GLOB */ - if(fnmatch(pat->s, hf->name.s, 0) !=0 ){ - *(hf->name.s+hf->name.len) = tmp; - continue; - } - } else if( matchtype == 'r' ){ /* REGEX */ - if(regexec(re, hf->name.s, 1, &pmatch, 0)!=0){ - *(hf->name.s+hf->name.len) = tmp; - continue; - } - } else { - LM_ERR("Unknow match type. Supported types are r (regex) and g (glob)"); - return -1; + tmp = *(hf->name.s+hf->name.len); + *(hf->name.s+hf->name.len) = 0; + if( matchtype == 'g' ) { /* GLOB */ + if(fnmatch(pat->s, hf->name.s, 0) !=0 ){ + *(hf->name.s+hf->name.len) = tmp; + continue; } - *(hf->name.s+hf->name.len) = tmp; - - /* check to see if the header was already removed */ - if (hf_already_removed(msg, hf->name.s-msg->buf, hf->len, - hf->type)) + } else if( matchtype == 'r' ){ /* REGEX */ + if(regexec(re, hf->name.s, 1, &pmatch, 0)!=0){ + *(hf->name.s+hf->name.len) = tmp; continue; - l=del_lump(msg, hf->name.s-msg->buf, hf->len, hf->type); - if (l==0) { - LM_ERR("no memory\n"); - return -1; } - cnt++; + } else { + LM_ERR("Unknow match type. Supported types are r (regex) and g (glob)"); + return -1; + } + *(hf->name.s+hf->name.len) = tmp; + + /* check to see if the header was already removed */ + if (hf_already_removed(msg, hf->name.s-msg->buf, hf->len, + hf->type)) + continue; + l=del_lump(msg, hf->name.s-msg->buf, hf->len, hf->type); + if (l==0) { + LM_ERR("no memory\n"); + return -1; + } + cnt++; } return cnt==0 ? -1 : 1; } @@ -563,7 +563,7 @@ static int is_present_hf_f(struct sip_msg* msg, char* str_hf, char* foo) gp = (gparam_p)str_hf; if (gp->type == GPARAM_TYPE_PVS && - parse_pvs_header(msg, gp) != 0) + parse_pvs_header(msg, gp) != 0) { LM_ERR("Parse pvs header failed!\n"); return -1; @@ -785,7 +785,7 @@ static int is_method_f(struct sip_msg *msg, char *meth, char *str2 ) return (msg->first_line.u.request.method_value==METHOD_OTHER && msg->first_line.u.request.method.len==m->len && (strncasecmp(msg->first_line.u.request.method.s, m->s, - m->len)==0))?1:-1; + m->len)==0))?1:-1; } if(parse_headers(msg, HDR_CSEQ_F, 0)!=0 || msg->cseq==NULL) { @@ -798,7 +798,7 @@ static int is_method_f(struct sip_msg *msg, char *meth, char *str2 ) return (get_cseq(msg)->method_id==METHOD_OTHER && get_cseq(msg)->method.len==m->len && (strncasecmp(get_cseq(msg)->method.s, m->s, - m->len)==0))?1:-1; + m->len)==0))?1:-1; } @@ -826,7 +826,7 @@ static int hname_fixup(void** param, int param_no) gp->v.sval.len++; if (parse_hname2(gp->v.sval.s, gp->v.sval.s - + ((gp->v.sval.len<4)?4:gp->v.sval.len), &hdr)==0) + + ((gp->v.sval.len<4)?4:gp->v.sval.len), &hdr)==0) { LM_ERR("error parsing header name\n"); pkg_free(gp); @@ -893,7 +893,7 @@ static int hname_match_fixup(void** param, int param_no) /* regex fixup code here */ LM_DBG("processing param1: %s as regex\n", *(char**)param); fixup_regexp_null(param, param_no); - }else if(type == 'g'){ + }else if(type == 'g'){ /* glob fixup code here */ LM_DBG("processing param1: %s as glob\n", *(char**)param); fixup_str(param); @@ -987,7 +987,7 @@ static int fixup_method(void** param, int param_no) if(method==METHOD_UNDEF || method&METHOD_OTHER) { LM_ERR("unknown method in list [%.*s/%d] - must be only defined methods\n", - s->len, s->s, method); + s->len, s->s, method); return E_UNSPEC; } LM_DBG("using id for methods [%.*s/%d]\n", @@ -998,12 +998,12 @@ static int fixup_method(void** param, int param_no) if(method!=METHOD_UNDEF && method!=METHOD_OTHER) { LM_DBG("using id for method [%.*s/%d]\n", - s->len, s->s, method); + s->len, s->s, method); s->s = 0; s->len = method; } else LM_DBG("name for method [%.*s/%d]\n", - s->len, s->s, method); + s->len, s->s, method); } *param = (void*)s; @@ -1015,24 +1015,24 @@ static int fixup_method(void** param, int param_no) */ static int fixup_privacy(void** param, int param_no) { - str p; - unsigned int val; + str p; + unsigned int val; - p.s = (char*)*param; - p.len = strlen(p.s); + p.s = (char*)*param; + p.len = strlen(p.s); - if (p.len == 0) { - LM_ERR("empty privacy value\n"); - return E_UNSPEC; - } + if (p.len == 0) { + LM_ERR("empty privacy value\n"); + return E_UNSPEC; + } - if (parse_priv_value(p.s, p.len, &val) != p.len) { - LM_ERR("invalid privacy value\n"); - return E_UNSPEC; - } + if (parse_priv_value(p.s, p.len, &val) != p.len) { + LM_ERR("invalid privacy value\n"); + return E_UNSPEC; + } - *param = (void *)(long)val; - return 0; + *param = (void *)(long)val; + return 0; } static int add_header_fixup(void** param, int param_no) @@ -1085,7 +1085,7 @@ static int has_body_f(struct sip_msg *msg, char *type, char *str2 ) /* parse content len hdr */ if ( msg->content_length==NULL && - (parse_headers(msg,HDR_CONTENTLENGTH_F, 0)==-1||msg->content_length==NULL)) + (parse_headers(msg,HDR_CONTENTLENGTH_F, 0)==-1||msg->content_length==NULL)) return -1; if (get_content_length (msg)==0) { @@ -1138,10 +1138,10 @@ static int has_body_f(struct sip_msg *msg, char *type, char *str2 ) static int is_privacy_f(struct sip_msg *msg, char *_privacy, char *str2 ) { - if (parse_privacy(msg) == -1) - return -1; + if (parse_privacy(msg) == -1) + return -1; - return get_privacy_values(msg) & ((unsigned int)(long)_privacy) ? 1 : -1; + return get_privacy_values(msg) & ((unsigned int)(long)_privacy) ? 1 : -1; } @@ -1190,7 +1190,7 @@ static int strip_body_f2(struct sip_msg *msg, char *type, char *str2 ) /* parse content len hdr */ if ( msg->content_length==NULL && - (parse_headers(msg,HDR_CONTENTLENGTH_F, 0)==-1||msg->content_length==NULL)) + (parse_headers(msg,HDR_CONTENTLENGTH_F, 0)==-1||msg->content_length==NULL)) return -1; if (get_content_length (msg)==0) { @@ -1238,7 +1238,7 @@ static int strip_body_f2(struct sip_msg *msg, char *type, char *str2 ) if( p->content_type == ((int)(long)type ) ) { if( del_lump( msg, p->all_data.s - msg->buf - 4 - m->boundary.len, - p->all_data.len + 6 + m->boundary.len, 0 ) == 0 ) + p->all_data.len + 6 + m->boundary.len, 0 ) == 0 ) { LM_ERR("Failed to add body lump\n"); return -1; @@ -1341,7 +1341,7 @@ static int add_body_f(struct sip_msg *msg, gparam_p nbody, gparam_p ctype ) } if(del_lump(msg, msg->content_type->name.s- msg->buf, msg->content_type->len, - HDR_CONTENTTYPE_T) == 0) { + HDR_CONTENTTYPE_T) == 0) { LM_ERR("failed to add lump to delete content type header\n"); return -1; } @@ -1397,8 +1397,8 @@ static int is_audio_on_hold_f(struct sip_msg *msg, char *str1, char *str2 ) sdp_stream = get_sdp_stream(msg, sdp_session_num, sdp_stream_num); if(!sdp_stream) break; if(sdp_stream->media.len==AUDIO_STR_LEN && - strncmp(sdp_stream->media.s,AUDIO_STR,AUDIO_STR_LEN)==0 && - sdp_stream->is_on_hold) + strncmp(sdp_stream->media.s,AUDIO_STR,AUDIO_STR_LEN)==0 && + sdp_stream->is_on_hold) return 1; sdp_stream_num++; } @@ -1453,20 +1453,20 @@ static int fixup_sip_validate(void** param, int param_no) flags |= SIP_PARSE_RURI; break; - case 't': - case 'T': - flags |= SIP_PARSE_TO; - break; - - case 'f': - case 'F': - flags |= SIP_PARSE_FROM; - break; - - case 'c': - case 'C': - flags |= SIP_PARSE_CONTACT; - break; + case 't': + case 'T': + flags |= SIP_PARSE_TO; + break; + + case 'f': + case 'F': + flags |= SIP_PARSE_FROM; + break; + + case 'c': + case 'C': + flags |= SIP_PARSE_CONTACT; + break; default: LM_DBG("unknown option \'%c\'\n", *flags_s); @@ -1504,25 +1504,25 @@ static int sip_validate_hdrs(struct sip_msg *msg) unsigned u_aux; int i_aux; - #define CHECK_HDR_EMPTY() \ - do { \ - str_aux = hf->body; \ - trim_len( str_aux.len , str_aux.s , hf->body ); \ - if (str_aux.len <= 0) { \ - LM_DBG("header '%.*s' has invalid value %d\n", \ - hf->name.len, hf->name.s, str_aux.len); \ - goto failed; \ - } \ - } while (0) - - #define CHECK_HDR_FUNC(_f, _o) \ - do { \ - if (_f(_o) < 0) { \ - LM_DBG("cannot parse '%.*s' header\n", \ - hf->name.len, hf->name.s); \ - goto failed; \ - } \ - } while (0) +#define CHECK_HDR_EMPTY() \ + do { \ + str_aux = hf->body; \ + trim_len( str_aux.len , str_aux.s , hf->body ); \ + if (str_aux.len <= 0) { \ + LM_DBG("header '%.*s' has invalid value %d\n", \ + hf->name.len, hf->name.s, str_aux.len); \ + goto failed; \ + } \ + } while (0) + +#define CHECK_HDR_FUNC(_f, _o) \ + do { \ + if (_f(_o) < 0) { \ + LM_DBG("cannot parse '%.*s' header\n", \ + hf->name.len, hf->name.s); \ + goto failed; \ + } \ + } while (0) /* skip via, cseq, to and content length * = we can be sure that they have been properly parsed = @@ -1552,13 +1552,13 @@ static int sip_validate_hdrs(struct sip_msg *msg) /* it seams we have to parse it! :-( */ e_aux = hf->body.s + hf->body.len; if ((s_aux = decode_mime_type(hf->body.s, e_aux , - &u_aux, cont)) == 0) { + &u_aux, cont)) == 0) { pkg_free(cont); goto failed; } if (e_aux != s_aux) { LM_DBG("the header CONTENT_TYPE contains " - "more then one mime type :-(!\n"); + "more than one mime type :-(!\n"); pkg_free(cont); goto failed; } @@ -1593,7 +1593,7 @@ static int sip_validate_hdrs(struct sip_msg *msg) case HDR_CONTENTDISPOSITION_T: if (!(disp = (struct disposition*) - pkg_malloc(sizeof(struct disposition)))) { + pkg_malloc(sizeof(struct disposition)))) { LM_ERR("no more pkg memory\n"); goto failed; } @@ -1608,7 +1608,7 @@ static int sip_validate_hdrs(struct sip_msg *msg) } break; - /* to-style headers */ + /* to-style headers */ case HDR_FROM_T: case HDR_PPI_T: case HDR_PAI_T: @@ -1737,9 +1737,9 @@ static int sip_validate_hdrs(struct sip_msg *msg) } #define IS_ALPHANUM(_c) ( \ - ((_c) >= 'a' && (_c) <= 'z') || \ - ((_c) >= 'A' && (_c) <= 'Z') || \ - ((_c) >= '0' && (_c) <= '9') ) + ((_c) >= 'a' && (_c) <= 'z') || \ + ((_c) >= 'A' && (_c) <= 'Z') || \ + ((_c) >= '0' && (_c) <= '9') ) static int check_hostname(str *domain) { @@ -1814,11 +1814,11 @@ enum sip_validation_failures { SV_NO_UNSUPPORTED=-19, SV_NO_WWW_AUTH=-20, SV_NO_CONTENT_TYPE=-21, - SV_TO_PARSE_ERROR=-22, - SV_TO_DOMAIN_ERROR=-23, - SV_FROM_PARSE_ERROR=-24, - SV_FROM_DOMAIN_ERROR=-25, - SV_CONTACT_PARSE_ERROR=-26, + SV_TO_PARSE_ERROR=-22, + SV_TO_DOMAIN_ERROR=-23, + SV_FROM_PARSE_ERROR=-24, + SV_FROM_DOMAIN_ERROR=-25, + SV_CONTACT_PARSE_ERROR=-26, SV_GENERIC_FAILURE=-255 }; @@ -1827,11 +1827,11 @@ static int w_sip_validate(struct sip_msg *msg, char *flags_s, char* pv_result) unsigned int hdrs_len; int method; str body; - struct hdr_field * ptr; - contact_t * contacts; - struct sip_uri test_contacts; + struct hdr_field * ptr; + contact_t * contacts; + struct sip_uri test_contacts; struct cseq_body * cbody; - struct to_body *from, *to; + struct to_body *from, *to; unsigned long flags; pv_elem_t* pv_res = (pv_elem_t*)pv_result; pv_value_t pv_val; @@ -1861,7 +1861,7 @@ static int w_sip_validate(struct sip_msg *msg, char *flags_s, char* pv_result) /* content length should be present if protocol is not UDP */ if (msg->rcv.proto != PROTO_UDP && !msg->content_length) { snprintf(reason, MAX_REASON-1, "message doesn't have Content Length header for proto %d", - msg->rcv.proto); + msg->rcv.proto); ret = SV_NO_CONTENT_LENGTH; goto failed; } @@ -1896,15 +1896,15 @@ static int w_sip_validate(struct sip_msg *msg, char *flags_s, char* pv_result) body.len = msg->buf + msg->len - body.s; if (get_content_length(msg) != body.len) { - snprintf(reason, MAX_REASON-1, "invalid body - content length %ld different then actual body %d", - get_content_length(msg), body.len); + snprintf(reason, MAX_REASON-1, "invalid body - content length %ld different than actual body %d", + get_content_length(msg), body.len); ret = SV_INVALID_CONTENT_LENGTH; goto failed; } /* if has body, check for SDP */ if (body.s && body.len && (flags & SIP_PARSE_SDP) && - parse_content_type_hdr(msg)==(TYPE_APPLICATION<<16 | SUBTYPE_SDP) ) { + parse_content_type_hdr(msg)==(TYPE_APPLICATION<<16 | SUBTYPE_SDP) ) { if (parse_sdp(msg) < 0) { strcpy(reason, "failed to parse SDP message"); ret = SV_PARSE_SDP; @@ -1932,58 +1932,58 @@ static int w_sip_validate(struct sip_msg *msg, char *flags_s, char* pv_result) /* check only if Via1 is present */ ret = SV_NO_VIA1; CHECK_HEADER("", via1); - + /* test to header uri */ - if(flags & SIP_PARSE_TO) { - if(!msg->to->parsed) { - if(parse_to_header(msg) < 0) { - strcpy(reason, "failed to parse \'To\' header"); - ret = SV_TO_PARSE_ERROR; - goto failed; - } - } - - to = (struct to_body*)msg->to->parsed; - - if(parse_uri(to->uri.s, to->uri.len, &to->parsed_uri) < 0) { - strcpy(reason, "failed to parse \'To\' header"); - ret = SV_TO_PARSE_ERROR; - goto failed; - } - - /* check for valid domain format */ - if(check_hostname(&to->parsed_uri.host) < 0) { - strcpy(reason, "invalid domain for \'To\' header"); - ret = SV_TO_DOMAIN_ERROR; - goto failed; - } - } - - /* test from header uri */ - if(flags & SIP_PARSE_FROM) { - if(!msg->from->parsed) { - if(parse_from_header(msg) < 0) { - strcpy(reason, "failed to parse \'From\' header"); - ret = SV_FROM_PARSE_ERROR; - goto failed; - } - } - - from = (struct to_body*)msg->from->parsed; - - if(parse_uri(from->uri.s, from->uri.len, &from->parsed_uri) < 0) { - strcpy(reason, "failed to parse \'From\' header"); - ret = SV_FROM_PARSE_ERROR; - goto failed; - } - - /* check for valid domain format */ - if(check_hostname(&from->parsed_uri.host) < 0) { - strcpy(reason, "invalid domain for \'From\' header"); - ret = SV_FROM_DOMAIN_ERROR; - goto failed; - } - } + if(flags & SIP_PARSE_TO) { + if(!msg->to->parsed) { + if(parse_to_header(msg) < 0) { + strcpy(reason, "failed to parse 'To' header"); + ret = SV_TO_PARSE_ERROR; + goto failed; + } + } + + to = (struct to_body*)msg->to->parsed; + + if(parse_uri(to->uri.s, to->uri.len, &to->parsed_uri) < 0) { + strcpy(reason, "failed to parse 'To' header"); + ret = SV_TO_PARSE_ERROR; + goto failed; + } + + /* check for valid domain format */ + if(check_hostname(&to->parsed_uri.host) < 0) { + strcpy(reason, "invalid domain for 'To' header"); + ret = SV_TO_DOMAIN_ERROR; + goto failed; + } + } + + /* test from header uri */ + if(flags & SIP_PARSE_FROM) { + if(!msg->from->parsed) { + if(parse_from_header(msg) < 0) { + strcpy(reason, "failed to parse 'From' header"); + ret = SV_FROM_PARSE_ERROR; + goto failed; + } + } + + from = (struct to_body*)msg->from->parsed; + + if(parse_uri(from->uri.s, from->uri.len, &from->parsed_uri) < 0) { + strcpy(reason, "failed to parse 'From' header"); + ret = SV_FROM_PARSE_ERROR; + goto failed; + } + + /* check for valid domain format */ + if(check_hostname(&from->parsed_uri.host) < 0) { + strcpy(reason, "invalid domain for 'From' header"); + ret = SV_FROM_DOMAIN_ERROR; + goto failed; + } + } /* request or reply */ switch (msg->first_line.type) { @@ -2011,154 +2011,154 @@ static int w_sip_validate(struct sip_msg *msg, char *flags_s, char* pv_result) if (msg->REQ_METHOD == METHOD_INVITE) { ret = SV_NO_CONTACT; CHECK_HEADER("INVITE", contact); - if(flags & SIP_PARSE_CONTACT) { - /* iterate through Contact headers */ - for(ptr = msg->contact; ptr; ptr = ptr->sibling) { - /* parse Contact header */ - if(!ptr->parsed && (parse_contact(ptr) < 0 - || !ptr->parsed)) { - strcpy(reason, "failed to parse \'Contact\' header"); - ret = SV_CONTACT_PARSE_ERROR; - goto failed; - } - contacts = ((contact_body_t*)ptr->parsed)->contacts; - /* empty contacts header - something must be wrong */ - if(contacts == NULL) { - strcpy(reason, "emtpy body for \'Contact\' header"); - ret = SV_CONTACT_PARSE_ERROR; - goto failed; - } - /* iterate through URIs and check validty */ - for(; contacts; contacts = contacts->next) { - if(parse_uri(contacts->uri.s, contacts->uri.len, - &test_contacts) < 0 - || test_contacts.host.len < 0) { - strcpy(reason, "failed to parse \'Contact\' header"); - ret = SV_CONTACT_PARSE_ERROR; - goto failed; - } - } - } - - } - } - - if (msg->REQ_METHOD != METHOD_REGISTER && msg->path) { - strcpy(reason, "PATH header supported only for REGISTERs"); - ret = SV_PATH_NONREGISTER; - goto failed; - } - - method = msg->REQ_METHOD; - - break; - - case SIP_REPLY: - /* checking the reply's message type */ - cbody = (struct cseq_body *)msg->cseq->parsed; - if (!cbody) { - strcpy(reason, "cseq not parsed properly"); - ret = SV_NO_CSEQ; - goto failed; - } - method = cbody->method_id; - if (method != METHOD_CANCEL) { - switch (msg->first_line.u.reply.statuscode) { - case 405: - ret = SV_NOALLOW_405; - CHECK_HEADER("", allow); - break; - - case 423: - if (method == METHOD_REGISTER) { - ret = SV_NOMINEXP_423; - CHECK_HEADER("REGISTER", min_expires); - } - break; - - case 407: - ret = SV_NO_PROXY_AUTH; - CHECK_HEADER("", proxy_authenticate); - break; - - case 420: - ret = SV_NO_UNSUPPORTED; - CHECK_HEADER("", unsupported); - break; - - case 401: - ret = SV_NO_WWW_AUTH; - CHECK_HEADER("", www_authenticate); - break; - } - } - - break; - - default: - strcpy(reason, "invalid message type"); - ret = SV_GENERIC_FAILURE; - goto failed; - } - /* check for body */ - if (method != METHOD_CANCEL) { - if (!msg->unparsed) { - strcpy(reason, "invalid parsing"); - ret = SV_HDR_PARSE_ERROR; - goto failed; - } - hdrs_len=(unsigned int)(msg->unparsed-msg->buf); - - if ((hdrs_len+2<=msg->len) && (strncmp(CRLF,msg->unparsed,CRLF_LEN)==0) ) - body.s = msg->unparsed + CRLF_LEN; - else if ( (hdrs_len+1<=msg->len) && - (*(msg->unparsed)=='\n' || *(msg->unparsed)=='\r' ) ) - body.s = msg->unparsed + 1; - else { - /* no body */ - body.s = NULL; - body.len = 0; - } - - /* determine the length of the body */ - body.len = msg->buf + msg->len - body.s; - - if (get_content_length(msg) != body.len) { - snprintf(reason, MAX_REASON-1, "invalid body - content length %ld different then " - "actual body %d\n", get_content_length(msg), body.len); - ret = SV_INVALID_CONTENT_LENGTH; - goto failed; - } - - if (body.len && body.s) { - /* if it really has body, check for content type */ - ret = SV_NO_CONTENT_TYPE; - CHECK_HEADER("", content_type); - } - } - - if ((flags & SIP_PARSE_HDR) && sip_validate_hdrs(msg) < 0) { - strcpy(reason, "failed to parse headers"); - ret = SV_HDR_PARSE_ERROR; - goto failed; - } - - return 1; + if(flags & SIP_PARSE_CONTACT) { + /* iterate through Contact headers */ + for(ptr = msg->contact; ptr; ptr = ptr->sibling) { + /* parse Contact header */ + if(!ptr->parsed && (parse_contact(ptr) < 0 + || !ptr->parsed)) { + strcpy(reason, "failed to parse 'Contact' header"); + ret = SV_CONTACT_PARSE_ERROR; + goto failed; + } + contacts = ((contact_body_t*)ptr->parsed)->contacts; + /* empty contacts header - something must be wrong */ + if(contacts == NULL) { + strcpy(reason, "emtpy body for 'Contact' header"); + ret = SV_CONTACT_PARSE_ERROR; + goto failed; + } + /* iterate through URIs and check validty */ + for(; contacts; contacts = contacts->next) { + if(parse_uri(contacts->uri.s, contacts->uri.len, + &test_contacts) < 0 + || test_contacts.host.len < 0) { + strcpy(reason, "failed to parse 'Contact' header"); + ret = SV_CONTACT_PARSE_ERROR; + goto failed; + } + } + } + + } + } + + if (msg->REQ_METHOD != METHOD_REGISTER && msg->path) { + strcpy(reason, "PATH header supported only for REGISTERs"); + ret = SV_PATH_NONREGISTER; + goto failed; + } + + method = msg->REQ_METHOD; + + break; + + case SIP_REPLY: + /* checking the reply's message type */ + cbody = (struct cseq_body *)msg->cseq->parsed; + if (!cbody) { + strcpy(reason, "cseq not parsed properly"); + ret = SV_NO_CSEQ; + goto failed; + } + method = cbody->method_id; + if (method != METHOD_CANCEL) { + switch (msg->first_line.u.reply.statuscode) { + case 405: + ret = SV_NOALLOW_405; + CHECK_HEADER("", allow); + break; + + case 423: + if (method == METHOD_REGISTER) { + ret = SV_NOMINEXP_423; + CHECK_HEADER("REGISTER", min_expires); + } + break; + + case 407: + ret = SV_NO_PROXY_AUTH; + CHECK_HEADER("", proxy_authenticate); + break; + + case 420: + ret = SV_NO_UNSUPPORTED; + CHECK_HEADER("", unsupported); + break; + + case 401: + ret = SV_NO_WWW_AUTH; + CHECK_HEADER("", www_authenticate); + break; + } + } + + break; + + default: + strcpy(reason, "invalid message type"); + ret = SV_GENERIC_FAILURE; + goto failed; + } + /* check for body */ + if (method != METHOD_CANCEL) { + if (!msg->unparsed) { + strcpy(reason, "invalid parsing"); + ret = SV_HDR_PARSE_ERROR; + goto failed; + } + hdrs_len=(unsigned int)(msg->unparsed-msg->buf); + + if ((hdrs_len+2<=msg->len) && (strncmp(CRLF,msg->unparsed,CRLF_LEN)==0) ) + body.s = msg->unparsed + CRLF_LEN; + else if ( (hdrs_len+1<=msg->len) && + (*(msg->unparsed)=='\n' || *(msg->unparsed)=='\r' ) ) + body.s = msg->unparsed + 1; + else { + /* no body */ + body.s = NULL; + body.len = 0; + } + + /* determine the length of the body */ + body.len = msg->buf + msg->len - body.s; + + if (get_content_length(msg) != body.len) { + snprintf(reason, MAX_REASON-1, "invalid body - content length %ld different than " + "actual body %d\n", get_content_length(msg), body.len); + ret = SV_INVALID_CONTENT_LENGTH; + goto failed; + } + + if (body.len && body.s) { + /* if it really has body, check for content type */ + ret = SV_NO_CONTENT_TYPE; + CHECK_HEADER("", content_type); + } + } + + if ((flags & SIP_PARSE_HDR) && sip_validate_hdrs(msg) < 0) { + strcpy(reason, "failed to parse headers"); + ret = SV_HDR_PARSE_ERROR; + goto failed; + } + + return 1; failed: - LM_DBG("message does not comply with SIP RFC3261 : (%s)\n", reason); - - if (pv_result != NULL) - { - pv_val.rs.len = strlen(reason); - pv_val.rs.s = reason; - pv_val.flags = PV_VAL_STR; - if (pv_set_value(msg, &pv_res->spec, 0, &pv_val) != 0) - { - LM_ERR("cannot populate parameter\n"); - return SV_GENERIC_FAILURE; - } - } - return ret; + LM_DBG("message does not comply with SIP RFC3261 : (%s)\n", reason); + + if (pv_result != NULL) + { + pv_val.rs.len = strlen(reason); + pv_val.rs.s = reason; + pv_val.flags = PV_VAL_STR; + if (pv_set_value(msg, &pv_res->spec, 0, &pv_val) != 0) + { + LM_ERR("cannot populate parameter\n"); + return SV_GENERIC_FAILURE; + } + } + return ret; } #undef CHECK_HEADER @@ -2168,73 +2168,73 @@ static int w_sip_validate(struct sip_msg *msg, char *flags_s, char* pv_result) /* Change_reply_status config parsing function (supports AVPs) */ static int change_reply_status_fixup(void** param, int param_no) { - if(param_no == 1) - return fixup_igp(param); + if(param_no == 1) + return fixup_igp(param); - if(param_no == 2) - return fixup_spve(param); + if(param_no == 2) + return fixup_spve(param); - return 0; + return 0; } /* Function to change the reply status in reply route */ static int change_reply_status_f(struct sip_msg* msg, char* str1, char* str2) { - int code_i; - str code_s; - struct lump *l; - char *ch; - - if(fixup_get_ivalue(msg, (gparam_p)str1, &code_i) < 0) { - LM_ERR("Wrong param 1, expected integer\n"); - return -1; - } - - if ( fixup_get_svalue(msg, (gparam_p) str2, &code_s) < 0) { - LM_ERR("Wrong param 2, expected string\n"); - return -1; - } - - if ((code_i < 100) || (code_i > 699)) { - LM_ERR("wrong status code: %d\n", code_i); - return -1; - } - - if (((code_i < 300) || (msg->REPLY_STATUS < 300)) - && (code_i/100 != msg->REPLY_STATUS/100)) { - LM_ERR("the class of provisional or positive final replies" - " cannot be changed\n"); - return -1; - } - - /* rewrite the status code directly in the message buffer */ - msg->first_line.u.reply.statuscode = code_i; - msg->first_line.u.reply.status.s[2] = code_i % 10 + '0'; code_i /= 10; - msg->first_line.u.reply.status.s[1] = code_i % 10 + '0'; code_i /= 10; - msg->first_line.u.reply.status.s[0] = code_i + '0'; - - l = del_lump(msg, - msg->first_line.u.reply.reason.s - msg->buf, - msg->first_line.u.reply.reason.len, - 0); - if (!l) { - LM_ERR("Failed to add del lump\n"); - return -1; - } - /* clone the reason phrase, the lumps need to be pkg allocated */ - ch = (char *)pkg_malloc(code_s.len); - if (!ch) { - LM_ERR("Not enough memory\n"); - return -1; - } - - memcpy(ch, code_s.s, code_s.len); - if (insert_new_lump_after(l, ch, code_s.len, 0)==0){ - LM_ERR("failed to add new lump: %.*s\n", code_s.len, ch); - pkg_free(ch); - return -1; - } - - return 1; + int code_i; + str code_s; + struct lump *l; + char *ch; + + if(fixup_get_ivalue(msg, (gparam_p)str1, &code_i) < 0) { + LM_ERR("Wrong param 1, expected integer\n"); + return -1; + } + + if ( fixup_get_svalue(msg, (gparam_p) str2, &code_s) < 0) { + LM_ERR("Wrong param 2, expected string\n"); + return -1; + } + + if ((code_i < 100) || (code_i > 699)) { + LM_ERR("wrong status code: %d\n", code_i); + return -1; + } + + if (((code_i < 300) || (msg->REPLY_STATUS < 300)) + && (code_i/100 != msg->REPLY_STATUS/100)) { + LM_ERR("the class of provisional or positive final replies" + " cannot be changed\n"); + return -1; + } + + /* rewrite the status code directly in the message buffer */ + msg->first_line.u.reply.statuscode = code_i; + msg->first_line.u.reply.status.s[2] = code_i % 10 + '0'; code_i /= 10; + msg->first_line.u.reply.status.s[1] = code_i % 10 + '0'; code_i /= 10; + msg->first_line.u.reply.status.s[0] = code_i + '0'; + + l = del_lump(msg, + msg->first_line.u.reply.reason.s - msg->buf, + msg->first_line.u.reply.reason.len, + 0); + if (!l) { + LM_ERR("Failed to add del lump\n"); + return -1; + } + /* clone the reason phrase, the lumps need to be pkg allocated */ + ch = (char *)pkg_malloc(code_s.len); + if (!ch) { + LM_ERR("Not enough memory\n"); + return -1; + } + + memcpy(ch, code_s.s, code_s.len); + if (insert_new_lump_after(l, ch, code_s.len, 0)==0){ + LM_ERR("failed to add new lump: %.*s\n", code_s.len, ch); + pkg_free(ch); + return -1; + } + + return 1; }