Module: sip-router
Branch: master
Commit: 8f007d20933f1d1deaac1c9c5ece9be2a4b9987c
URL:    
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=8f007d20933f1d1deaac1c9c5ece9be2a4b9987c

Author: Victor Seva <[email protected]>
Committer: Victor Seva <[email protected]>
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(&params, 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


_______________________________________________
sr-dev mailing list
[email protected]
http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev

Reply via email to