Module: sip-router Branch: master Commit: 8f007d20933f1d1deaac1c9c5ece9be2a4b9987c URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=8f007d20...
Author: Victor Seva linuxmaniac@torreviejawireless.org Committer: Victor Seva linuxmaniac@torreviejawireless.org Date: Fri Mar 21 21:56:04 2014 +0100
core: add check_boundaries() to build_req_buf_from_sip_req().
This checks and fixes the boundaries of a multipart body if the FL_BODY_MULTIPART flag is set.
---
msg_translator.c | 302 +++++++++++++++++++++++++++++++++++++++++++++++++++++- msg_translator.h | 3 + 2 files changed, 302 insertions(+), 3 deletions(-)
diff --git a/msg_translator.c b/msg_translator.c index 23a9157..6020fce 100644 --- a/msg_translator.c +++ b/msg_translator.c @@ -147,8 +147,9 @@ #include "pt.h" #include "cfg/cfg.h" #include "parser/parse_to.h" +#include "parser/parse_param.h" #include "forward.h" - +#include "str_list.h"
#define append_str_trans(_dest,_src,_len,_msg) \ append_str( (_dest), (_src), (_len) ); @@ -1620,7 +1621,301 @@ error: return -1; }
+static inline int find_line_start(char *text, unsigned int text_len, + char **buf, unsigned int *buf_len) +{ + char *ch, *start; + unsigned int 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; + } + } + return 0; +} + +static inline int get_line(str s) +{ + char *ch; + + if ((ch = memchr(s.s, 13, s.len))) { + if (*(ch + 1) != 10) { + LM_ERR("No LF after CR\n"); + return 0; + } + return ch - s.s + 2; + } else { + LM_ERR("No CRLF found\n"); + return s.len; + } + return 0; +} + +int replace_body(struct sip_msg *msg, str txt) +{ + struct lump *anchor; + char *buf; + str body = {0,0}; + + body.s = get_body(msg); + if(body.s==0) + { + LM_ERR("malformed sip message\n"); + return 0; + } + body.len = msg->len -(int)(body.s-msg->buf); + LM_DBG("old size body[%d] actual[%d]\n", body.len, txt.len); + if(body.s+body.len>msg->buf+msg->len) + { + LM_ERR("invalid content length: %d\n", body.len); + return 0; + } + del_nonshm_lump( &(msg->body_lumps) ); + msg->body_lumps = NULL; + + if(del_lump(msg, body.s-msg->buf, body.len, 0) == 0) + { + LM_ERR("cannot delete existing body"); + return 0; + } + + anchor = anchor_lump(msg, body.s - msg->buf, 0, 0); + if(anchor==0) + { + LM_ERR("failed to get anchor\n"); + return 0; + } + + buf=pkg_malloc(sizeof(char)*txt.len); + if(buf==0) + { + PKG_MEM_ERROR; + return 0; + } + memcpy(buf, txt.s, txt.len); + if(insert_new_lump_after(anchor, buf, txt.len, 0)==0) + { + LM_ERR("failed to insert body lump\n"); + pkg_free(buf); + return 0; + } + return 1; +} + +/** + * returns the boundary defined by the Content-Type + * header + */ +int get_boundary(struct sip_msg* msg, str* boundary) +{ + str params; + param_t *p, *list; + param_hooks_t hooks; + + params.s = memchr(msg->content_type->body.s, ';', + msg->content_type->body.len); + if (params.s == NULL) + { + LM_ERR("Content-Type hdr has no params\n"); + return -1; + } + params.len = msg->content_type->body.len - + (params.s - msg->content_type->body.s); + if (parse_params(¶ms, CLASS_ANY, &hooks, &list) < 0) + { + LM_ERR("while parsing Content-Type params\n"); + return -1; + } + boundary->s = NULL; + boundary->len = 0; + for (p = list; p; p = p->next) { + if ((p->name.len == 8) + && (strncasecmp(p->name.s, "boundary", 8) == 0)) + { + boundary->s = pkg_malloc(p->body.len + 2); + if (boundary->s == NULL) + { + free_params(list); + LM_ERR("no memory for boundary string\n"); + return -1; + } + *(boundary->s) = '-'; + *(boundary->s + 1) = '-'; + memcpy(boundary->s + 2, p->body.s, p->body.len); + boundary->len = 2 + p->body.len; + LM_DBG("boundary is <%.*s>\n", boundary->len, boundary->s); + break; + } + } + free_params(list); + return 0; +} + +int check_boundaries(struct sip_msg *msg, struct dest_info *send_info) +{ + str b = {0,0}; + str fb = {0,0}; + str ob = {0,0}; + str bsuffix = {"\r\n", 2}; + str fsuffix = {"--\r\n", 4}; + str body = {0,0}; + str buf = {0,0}; + str tmp = {0,0}; + struct str_list* lb = NULL; + struct str_list* lb_t = NULL; + int lb_found = 0; + int t, ret, lb_size; + char *pb; + + if(!(msg->msg_flags&FL_BODY_MULTIPART)) return 0; + else + { + buf.s = build_body(msg, (unsigned int *)&buf.len, &ret, send_info); + if(ret) { + LM_ERR("Can't get body\n"); + return -1; + } + tmp.s = buf.s; + t = tmp.len = buf.len; + if(get_boundary(msg, &ob)!=0) return -1; + if(str_append(&ob, &bsuffix, &b)!=0) { + LM_ERR("Can't append suffix to boundary\n"); + goto error; + } + if(str_append(&ob, &fsuffix,&fb)!=0) { + LM_ERR("Can't append suffix to final boundary\n"); + goto error; + } + ret = b.len-2; + while(t>0) + { + if(find_line_start(b.s, ret, &tmp.s, + (unsigned int *)&tmp.len)) + { + /*LM_DBG("found t[%d] tmp.len[%d]:[%.*s]\n", + t, tmp.len, tmp.len, tmp.s);*/ + if(!lb) + { + lb = pkg_malloc(sizeof(struct str_list)); + if (!lb) { + PKG_MEM_ERROR; + goto error; + } + lb->s.s = tmp.s; + lb->s.len = tmp.len; + lb->next = 0; + lb_t = lb; + } + else + { + lb_t = append_str_list(tmp.s, tmp.len, &lb_t, &lb_size); + } + lb_found = lb_found + 1; + tmp.s = tmp.s + ret; + t = t - ret; + tmp.len = tmp.len - ret; + } + else { t=0; } + } + if(lb_found<2) + { + LM_ERR("found[%d] wrong number of boundaries\n", lb_found); + goto error; + } + /* adding 2 chars in advance */ + body.len = buf.len + 2; + body.s = pkg_malloc(sizeof(char)*body.len); + if (!body.s) { + PKG_MEM_ERROR; + goto error; + } + pb = body.s; body.len = 0; + lb_t = lb; + while(lb_t) + { + tmp.s = lb_t->s.s; tmp.len = lb_t->s.len; + tmp.len = get_line(lb_t->s); + if(tmp.len!=b.len || strncmp(b.s, tmp.s, b.len)!=0) + { + LM_DBG("malformed bondary in the middle\n"); + memcpy(pb, b.s, b.len); body.len = body.len + b.len; + pb = pb + b.len; + t = lb_t->s.s - (lb_t->s.s + tmp.len); + memcpy(pb, lb_t->s.s+tmp.len, t); pb = pb + t; + /*LM_DBG("new chunk[%d][%.*s]\n", t, t, pb-t);*/ + } + else { + t = lb_t->next->s.s - lb_t->s.s; + memcpy(pb, lb_t->s.s, t); + /*LM_DBG("copy[%d][%.*s]\n", t, t, pb);*/ + pb = pb + t; + } + body.len = body.len + t; + /*LM_DBG("body[%d][%.*s]\n", body.len, body.len, body.s);*/ + lb_t = lb_t->next; + if(!lb_t->next) lb_t = NULL; + } + /* last boundary */ + tmp.s = lb->s.s; tmp.len = lb->s.len; + tmp.len = get_line(lb->s); + if(tmp.len!=fb.len || strncmp(fb.s, tmp.s, fb.len)!=0) + { + LM_DBG("last bondary without -- at the end\n"); + memcpy(pb, fb.s, fb.len); + /*LM_DBG("new chunk[%d][%.*s]\n", fb.len, fb.len, pb);*/ + pb = pb + fb.len; + body.len = body.len + fb.len; + } + else { + memcpy(pb, lb->s.s, lb->s.len); pb = pb + lb->s.len; + body.len = body.len + lb->s.len; + /*LM_DBG("copy[%d][%.*s]\n", lb->s.len, lb->s.len, pb - lb->s.len);*/ + } + /*LM_DBG("body[%d][%.*s] expected[%ld]\n", + body.len, body.len, body.s, pb-body.s); */ + if(!replace_body(msg, body)) + { + LM_ERR("Can't replace body\n"); + goto error; + } + msg->msg_flags &= ~FL_BODY_MULTIPART; + ret = 1; + goto clean; + }
+error: + ret = -1; +clean: + if(ob.s) pkg_free(ob.s); + if(b.s) pkg_free(b.s); + if(fb.s) pkg_free(fb.s); + if(body.s) pkg_free(body.s); + if(buf.s) pkg_free(buf.s); + while(lb) + { + lb_t = lb->next; + pkg_free(lb); + lb = lb_t; + } + return ret; +}
/** builds a request in memory from another sip request. * @@ -1700,6 +1995,9 @@ char * build_req_buf_from_sip_req( struct sip_msg* msg, path_buf.len=0;
flags=msg->msg_flags|global_req_flags; + if(check_boundaries(msg, send_info)<0){ + LM_WARN("check_boundaries error\n"); + } /* Calculate message body difference and adjust Content-Length */ body_delta = lumps_len(msg, msg->body_lumps, send_info); if (adjust_clen(msg, body_delta, send_info->proto) < 0) { @@ -1956,8 +2254,6 @@ error00: return 0; }
- - char * generate_res_buf_from_sip_res( struct sip_msg* msg, unsigned int *returned_len, unsigned int mode) { diff --git a/msg_translator.h b/msg_translator.h index 4848291..42c16b7 100644 --- a/msg_translator.h +++ b/msg_translator.h @@ -162,4 +162,7 @@ void fix_global_req_flags(str* gname, str* name);
int build_sip_msg_from_buf(struct sip_msg *msg, char *buf, int len, unsigned int id); + +/* returns a copy in private memory of the boundary in a multipart body */ +int get_boundary(struct sip_msg* msg, str* boundary); #endif