Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support overlapping SIP&HTTP headers in WS HTTP initial requests #3237

Merged
merged 1 commit into from
Oct 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions modules/proto_ws/ws_handshake_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -844,7 +844,7 @@ static int ws_parse_req_handshake(struct tcp_connection *c, char *msg, int len)
memset(&tmp_msg, 0, sizeof(struct sip_msg));
tmp_msg.len = len;
tmp_msg.buf = tmp_msg.unparsed = msg;
if (parse_headers(&tmp_msg, HDR_EOH_F, 0) < 0) {
if (parse_headers_aux(&tmp_msg, HDR_EOH_F, 0,0) < 0) {
LM_ERR("cannot parse headers\n%.*s\n", len, msg);
goto error;
}
Expand Down Expand Up @@ -1122,7 +1122,7 @@ static int ws_parse_rpl_handshake(struct tcp_connection *c, char *msg, int len)
memset(&tmp_msg, 0, sizeof(struct sip_msg));
tmp_msg.len = len;
tmp_msg.buf = tmp_msg.unparsed = msg;
if (parse_headers(&tmp_msg, HDR_EOH_F, 0) < 0) {
if (parse_headers_aux(&tmp_msg, HDR_EOH_F, 0, 0) < 0) {
LM_ERR("cannot parse headers\n%.*s\n", len, msg);
goto error;
}
Expand Down
260 changes: 172 additions & 88 deletions parser/msg_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ int via_cnt;

/* returns pointer to next header line, and fill hdr_f ;
* if at end of header returns pointer to the last crlf (always buf)*/
char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr)
char* get_hdr_field_aux(char* buf, char* end, struct hdr_field* hdr,int sip_well_known_parse)
{

char* tmp;
Expand Down Expand Up @@ -107,88 +107,172 @@ char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr)
/* keep number of vias parsed -- we want to report it in
replies for diagnostic purposes */
via_cnt++;
vb=pkg_malloc(sizeof(struct via_body));
if (vb==0){
LM_ERR("out of pkg memory\n");
goto error;
}
memset(vb,0,sizeof(struct via_body));
hdr->body.s=tmp;
tmp=parse_via(tmp, end, vb);
if (vb->error==PARSE_ERROR){
LM_ERR("bad via\n");
free_via_list(vb);
set_err_info(OSER_EC_PARSER, OSER_EL_MEDIUM,
"error parsing Via");
set_err_reply(400, "bad Via header");
goto error;
if (sip_well_known_parse) {
vb=pkg_malloc(sizeof(struct via_body));
if (vb==0){
LM_ERR("out of pkg memory\n");
goto error;
}
memset(vb,0,sizeof(struct via_body));
hdr->body.s=tmp;
tmp=parse_via(tmp, end, vb);
if (vb->error==PARSE_ERROR){
LM_ERR("bad via\n");
free_via_list(vb);
set_err_info(OSER_EC_PARSER, OSER_EL_MEDIUM,
"error parsing Via");
set_err_reply(400, "bad Via header");
goto error;
}
hdr->parsed=vb;
vb->hdr.s=hdr->name.s;
vb->hdr.len=hdr->name.len;
hdr->body.len=tmp-hdr->body.s;
} else {
/* just skip over it */
hdr->body.s=tmp;
/* find end of header */
/* find lf */
do{
match=q_memchr(tmp, '\n', end-tmp);
if (match){
match++;
}else {
LM_ERR("bad body for <%.*s>(%d)\n",
hdr->name.len, hdr->name.s, hdr->type);
tmp=end;
goto error_bad_hdr;
}
tmp=match;
}while( match<end &&( (*match==' ')||(*match=='\t') ) );
tmp=match;
hdr->body.len=match-hdr->body.s;
}
hdr->parsed=vb;
vb->hdr.s=hdr->name.s;
vb->hdr.len=hdr->name.len;
hdr->body.len=tmp-hdr->body.s;
break;
case HDR_CSEQ_T:
cseq_b=pkg_malloc(sizeof(struct cseq_body));
if (cseq_b==0){
LM_ERR("out of pkg memory\n");
goto error;
}
memset(cseq_b, 0, sizeof(struct cseq_body));
hdr->body.s=tmp;
tmp=parse_cseq(tmp, end, cseq_b);
if (cseq_b->error==PARSE_ERROR){
LM_ERR("bad cseq\n");
pkg_free(cseq_b);
set_err_info(OSER_EC_PARSER, OSER_EL_MEDIUM,
"error parsing CSeq`");
set_err_reply(400, "bad CSeq header");
goto error;
if (sip_well_known_parse) {
cseq_b=pkg_malloc(sizeof(struct cseq_body));
if (cseq_b==0){
LM_ERR("out of pkg memory\n");
goto error;
}
memset(cseq_b, 0, sizeof(struct cseq_body));
hdr->body.s=tmp;
tmp=parse_cseq(tmp, end, cseq_b);
if (cseq_b->error==PARSE_ERROR){
LM_ERR("bad cseq\n");
pkg_free(cseq_b);
set_err_info(OSER_EC_PARSER, OSER_EL_MEDIUM,
"error parsing CSeq`");
set_err_reply(400, "bad CSeq header");
goto error;
}
hdr->parsed=cseq_b;
hdr->body.len=tmp-hdr->body.s;
LM_DBG("cseq <%.*s>: <%.*s> <%.*s>\n",
hdr->name.len, ZSW(hdr->name.s),
cseq_b->number.len, ZSW(cseq_b->number.s),
cseq_b->method.len, cseq_b->method.s);
} else {
/* just skip over it */
hdr->body.s=tmp;
/* find end of header */
/* find lf */
do{
match=q_memchr(tmp, '\n', end-tmp);
if (match){
match++;
}else {
LM_ERR("bad body for <%.*s>(%d)\n",
hdr->name.len, hdr->name.s, hdr->type);
tmp=end;
goto error_bad_hdr;
}
tmp=match;
}while( match<end &&( (*match==' ')||(*match=='\t') ) );
tmp=match;
hdr->body.len=match-hdr->body.s;
}
hdr->parsed=cseq_b;
hdr->body.len=tmp-hdr->body.s;
LM_DBG("cseq <%.*s>: <%.*s> <%.*s>\n",
hdr->name.len, ZSW(hdr->name.s),
cseq_b->number.len, ZSW(cseq_b->number.s),
cseq_b->method.len, cseq_b->method.s);
break;
case HDR_TO_T:
to_b=pkg_malloc(sizeof(struct to_body));
if (to_b==0){
LM_ERR("out of pkg memory\n");
goto error;
}
memset(to_b, 0, sizeof(struct to_body));
hdr->body.s=tmp;
tmp=parse_to(tmp, end,to_b);
if (to_b->error==PARSE_ERROR){
LM_ERR("bad to header\n");
pkg_free(to_b);
set_err_info(OSER_EC_PARSER, OSER_EL_MEDIUM,
"error parsing To header");
set_err_reply(400, "bad header");
goto error;
if (sip_well_known_parse) {
to_b=pkg_malloc(sizeof(struct to_body));
if (to_b==0){
LM_ERR("out of pkg memory\n");
goto error;
}
memset(to_b, 0, sizeof(struct to_body));
hdr->body.s=tmp;
tmp=parse_to(tmp, end,to_b);
if (to_b->error==PARSE_ERROR){
LM_ERR("bad to header\n");
pkg_free(to_b);
set_err_info(OSER_EC_PARSER, OSER_EL_MEDIUM,
"error parsing To header");
set_err_reply(400, "bad header");
goto error;
}
hdr->parsed=to_b;
hdr->body.len=tmp-hdr->body.s;
LM_DBG("<%.*s> [%d]; uri=[%.*s] \n",
hdr->name.len, ZSW(hdr->name.s),
hdr->body.len, to_b->uri.len,ZSW(to_b->uri.s));
LM_DBG("to body [%.*s]\n",to_b->body.len, ZSW(to_b->body.s));
} else {
/* just skip over it */
hdr->body.s=tmp;
/* find end of header */
/* find lf */
do{
match=q_memchr(tmp, '\n', end-tmp);
if (match){
match++;
}else {
LM_ERR("bad body for <%.*s>(%d)\n",
hdr->name.len, hdr->name.s, hdr->type);
tmp=end;
goto error_bad_hdr;
}
tmp=match;
}while( match<end &&( (*match==' ')||(*match=='\t') ) );
tmp=match;
hdr->body.len=match-hdr->body.s;
}
hdr->parsed=to_b;
hdr->body.len=tmp-hdr->body.s;
LM_DBG("<%.*s> [%d]; uri=[%.*s] \n",
hdr->name.len, ZSW(hdr->name.s),
hdr->body.len, to_b->uri.len,ZSW(to_b->uri.s));
LM_DBG("to body [%.*s]\n",to_b->body.len, ZSW(to_b->body.s));
break;
case HDR_CONTENTLENGTH_T:
hdr->body.s=tmp;
tmp=parse_content_length(tmp,end, &integer);
if (tmp==0){
LM_ERR("bad content_length header\n");
set_err_info(OSER_EC_PARSER, OSER_EL_MEDIUM,
"error parsing Content-Length");
set_err_reply(400, "bad Content-Length header");
goto error;
if (sip_well_known_parse) {
hdr->body.s=tmp;
tmp=parse_content_length(tmp,end, &integer);
if (tmp==0){
LM_ERR("bad content_length header\n");
set_err_info(OSER_EC_PARSER, OSER_EL_MEDIUM,
"error parsing Content-Length");
set_err_reply(400, "bad Content-Length header");
goto error;
}
hdr->parsed=(void*)(long)integer;
hdr->body.len=tmp-hdr->body.s;
LM_DBG("content_length=%d\n", (int)(long)hdr->parsed);
} else {
/* just skip over it */
hdr->body.s=tmp;
/* find end of header */
/* find lf */
do{
match=q_memchr(tmp, '\n', end-tmp);
if (match){
match++;
}else {
LM_ERR("bad body for <%.*s>(%d)\n",
hdr->name.len, hdr->name.s, hdr->type);
tmp=end;
goto error_bad_hdr;
}
tmp=match;
}while( match<end &&( (*match==' ')||(*match=='\t') ) );
tmp=match;
hdr->body.len=match-hdr->body.s;
}
hdr->parsed=(void*)(long)integer;
hdr->body.len=tmp-hdr->body.s;
LM_DBG("content_length=%d\n", (int)(long)hdr->parsed);
break;
case HDR_SUPPORTED_T:
case HDR_CONTENTTYPE_T:
Expand Down Expand Up @@ -278,8 +362,6 @@ char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr)
return tmp;
}



/* parse the headers and adds them to msg->headers and msg->to, from etc.
* It stops when all the headers requested in flags were parsed, on error
* (bad header) or end of headers */
Expand All @@ -292,7 +374,7 @@ char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr)
give you the first occurrence of a header you are interested in,
look at check_transaction_quadruple
*/
int parse_headers(struct sip_msg* msg, hdr_flags_t flags, int next)
int parse_headers_aux(struct sip_msg* msg, hdr_flags_t flags, int next, int sip_well_known_parse)
{
struct hdr_field *hf;
struct hdr_field *itr;
Expand Down Expand Up @@ -329,7 +411,7 @@ int parse_headers(struct sip_msg* msg, hdr_flags_t flags, int next)
}
memset(hf,0, sizeof(struct hdr_field));
hf->type=HDR_ERROR_T;
rest=get_hdr_field(tmp, msg->buf+msg->len, hf);
rest=get_hdr_field_aux(tmp, msg->buf+msg->len, hf,sip_well_known_parse);
switch (hf->type){
case HDR_ERROR_T:
LM_INFO("bad header field\n");
Expand Down Expand Up @@ -511,19 +593,21 @@ int parse_headers(struct sip_msg* msg, hdr_flags_t flags, int next)
link_sibling_hdr(h_via1,hf);
msg->parsed_flag|=HDR_VIA_F;
LM_DBG("via found, flags=%llx\n", (unsigned long long)flags);
if (msg->via1==0) {
LM_DBG("this is the first via\n");
msg->h_via1=hf;
msg->via1=hf->parsed;
if (msg->via1->next){
msg->via2=msg->via1->next;
if (sip_well_known_parse) {
if (msg->via1==0) {
LM_DBG("this is the first via\n");
msg->h_via1=hf;
msg->via1=hf->parsed;
if (msg->via1->next){
msg->via2=msg->via1->next;
msg->parsed_flag|=HDR_VIA2_F;
}
}else if (msg->via2==0){
msg->h_via2=hf;
msg->via2=hf->parsed;
msg->parsed_flag|=HDR_VIA2_F;
LM_DBG("parse_headers: this is the second via\n");
}
}else if (msg->via2==0){
msg->h_via2=hf;
msg->via2=hf->parsed;
msg->parsed_flag|=HDR_VIA2_F;
LM_DBG("parse_headers: this is the second via\n");
}
break;
case HDR_FEATURE_CAPS_T:
Expand Down
8 changes: 6 additions & 2 deletions parser/msg_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -355,9 +355,13 @@ extern int via_cnt;

int parse_msg(char* buf, unsigned int len, struct sip_msg* msg);

int parse_headers(struct sip_msg* msg, hdr_flags_t flags, int next);
#define parse_headers(msg, flags,next) parse_headers_aux(msg,flags,next, 1)

char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr);
int parse_headers_aux(struct sip_msg* msg, hdr_flags_t flags, int next, int sip_well_known_parse);

#define get_hdr_field(buf,end,hdr) get_hdr_field_aux(buf,end,hdr,1)

char* get_hdr_field_aux(char* buf, char* end, struct hdr_field* hdr, int sip_well_known_parse);

void free_sip_msg(struct sip_msg* msg);

Expand Down