[sr-dev] git:master: core: add check_boundaries() to build_req_buf_from_sip_req().

Victor Seva linuxmaniac at torreviejawireless.org
Sun May 18 20:08:24 CEST 2014


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 <linuxmaniac at torreviejawireless.org>
Committer: Victor Seva <linuxmaniac at 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(&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




More information about the sr-dev mailing list