Module: sip-router
Branch: master
Commit: 8f007d20933f1d1deaac1c9c5ece9be2a4b9987c
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=8f007d2…
Author: Victor Seva <linuxmaniac(a)torreviejawireless.org>
Committer: Victor Seva <linuxmaniac(a)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