Browse code

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.

Victor Seva authored on 21/03/2014 20:56:04
Showing 2 changed files
... ...
@@ -147,8 +147,9 @@
147 147
 #include "pt.h"
148 148
 #include "cfg/cfg.h"
149 149
 #include "parser/parse_to.h"
150
+#include "parser/parse_param.h"
150 151
 #include "forward.h"
151
-
152
+#include "str_list.h"
152 153
 
153 154
 #define append_str_trans(_dest,_src,_len,_msg) \
154 155
 	append_str( (_dest), (_src), (_len) );
... ...
@@ -1620,7 +1621,301 @@ error:
1620 1620
 	return -1;
1621 1621
 }
1622 1622
 
1623
+static inline int find_line_start(char *text, unsigned int text_len,
1624
+				  char **buf, unsigned int *buf_len)
1625
+{
1626
+	char *ch, *start;
1627
+	unsigned int len;
1628
+
1629
+	start = *buf;
1630
+	len = *buf_len;
1631
+
1632
+	while (text_len <= len) {
1633
+		if (strncmp(text, start, text_len) == 0) {
1634
+			*buf = start;
1635
+			*buf_len = len;
1636
+			return 1;
1637
+		}
1638
+		if ((ch = memchr(start, 13, len - 1))) {
1639
+			if (*(ch + 1) != 10) {
1640
+				LM_ERR("No LF after CR\n");
1641
+				return 0;
1642
+			}
1643
+			len = len - (ch - start + 2);
1644
+			start = ch + 2;
1645
+		} else {
1646
+			LM_ERR("No CRLF found\n");
1647
+			return 0;
1648
+		}
1649
+	}
1650
+	return 0;
1651
+}
1652
+
1653
+static inline int get_line(str s)
1654
+{
1655
+	char *ch;
1656
+
1657
+	if ((ch = memchr(s.s, 13, s.len))) {
1658
+		if (*(ch + 1) != 10) {
1659
+			LM_ERR("No LF after CR\n");
1660
+			return 0;
1661
+		}
1662
+		return ch - s.s + 2;
1663
+	} else {
1664
+		LM_ERR("No CRLF found\n");
1665
+		return s.len;
1666
+	}
1667
+	return 0;
1668
+}
1669
+
1670
+int replace_body(struct sip_msg *msg, str txt)
1671
+{
1672
+	struct lump *anchor;
1673
+	char *buf;
1674
+	str body = {0,0};
1675
+
1676
+	body.s = get_body(msg);
1677
+	if(body.s==0)
1678
+	{
1679
+		LM_ERR("malformed sip message\n");
1680
+		return 0;
1681
+	}
1682
+	body.len = msg->len -(int)(body.s-msg->buf);
1683
+	LM_DBG("old size body[%d] actual[%d]\n", body.len, txt.len);
1684
+	if(body.s+body.len>msg->buf+msg->len)
1685
+	{
1686
+		LM_ERR("invalid content length: %d\n", body.len);
1687
+		return 0;
1688
+	}
1689
+	del_nonshm_lump( &(msg->body_lumps) );
1690
+	msg->body_lumps = NULL;
1691
+
1692
+	if(del_lump(msg, body.s-msg->buf, body.len, 0) == 0)
1693
+	{
1694
+		LM_ERR("cannot delete existing body");
1695
+		return 0;
1696
+	}
1697
+
1698
+	anchor = anchor_lump(msg, body.s - msg->buf, 0, 0);
1699
+	if(anchor==0)
1700
+	{
1701
+		LM_ERR("failed to get anchor\n");
1702
+		return 0;
1703
+	}
1704
+
1705
+	buf=pkg_malloc(sizeof(char)*txt.len);
1706
+	if(buf==0)
1707
+	{
1708
+		PKG_MEM_ERROR;
1709
+		return 0;
1710
+	}
1711
+	memcpy(buf, txt.s, txt.len);
1712
+	if(insert_new_lump_after(anchor, buf, txt.len, 0)==0)
1713
+	{
1714
+		LM_ERR("failed to insert body lump\n");
1715
+		pkg_free(buf);
1716
+		return 0;
1717
+	}
1718
+	return 1;
1719
+}
1720
+
1721
+/**
1722
+ * returns the boundary defined by the Content-Type
1723
+ * header
1724
+ */
1725
+int get_boundary(struct sip_msg* msg, str* boundary)
1726
+{
1727
+	str params;
1728
+	param_t *p, *list;
1729
+	param_hooks_t hooks;
1730
+
1731
+	params.s = memchr(msg->content_type->body.s, ';',
1732
+		msg->content_type->body.len);
1733
+	if (params.s == NULL)
1734
+	{
1735
+		LM_ERR("Content-Type hdr has no params\n");
1736
+		return -1;
1737
+	}
1738
+	params.len = msg->content_type->body.len -
1739
+		(params.s - msg->content_type->body.s);
1740
+	if (parse_params(&params, CLASS_ANY, &hooks, &list) < 0)
1741
+	{
1742
+		LM_ERR("while parsing Content-Type params\n");
1743
+		return -1;
1744
+	}
1745
+	boundary->s = NULL;
1746
+	boundary->len = 0;
1747
+	for (p = list; p; p = p->next) {
1748
+		if ((p->name.len == 8)
1749
+			&& (strncasecmp(p->name.s, "boundary", 8) == 0))
1750
+		{
1751
+			boundary->s = pkg_malloc(p->body.len + 2);
1752
+			if (boundary->s == NULL)
1753
+			{
1754
+				free_params(list);
1755
+				LM_ERR("no memory for boundary string\n");
1756
+				return -1;
1757
+			}
1758
+			*(boundary->s) = '-';
1759
+			*(boundary->s + 1) = '-';
1760
+			memcpy(boundary->s + 2, p->body.s, p->body.len);
1761
+			boundary->len = 2 + p->body.len;
1762
+			LM_DBG("boundary is <%.*s>\n", boundary->len, boundary->s);
1763
+			break;
1764
+		}
1765
+	}
1766
+	free_params(list);
1767
+	return 0;
1768
+}
1769
+
1770
+int check_boundaries(struct sip_msg *msg, struct dest_info *send_info)
1771
+{
1772
+	str b = {0,0};
1773
+	str fb = {0,0};
1774
+	str ob = {0,0};
1775
+	str bsuffix = {"\r\n", 2};
1776
+	str fsuffix = {"--\r\n", 4};
1777
+	str body = {0,0};
1778
+	str buf = {0,0};
1779
+	str tmp = {0,0};
1780
+	struct str_list* lb = NULL;
1781
+	struct str_list* lb_t = NULL;
1782
+	int lb_found = 0;
1783
+	int t, ret, lb_size;
1784
+	char *pb;
1785
+
1786
+	if(!(msg->msg_flags&FL_BODY_MULTIPART)) return 0;
1787
+	else
1788
+	{
1789
+		buf.s = build_body(msg, (unsigned int *)&buf.len, &ret, send_info);
1790
+		if(ret) {
1791
+			LM_ERR("Can't get body\n");
1792
+			return -1;
1793
+		}
1794
+		tmp.s = buf.s;
1795
+		t = tmp.len = buf.len;
1796
+		if(get_boundary(msg, &ob)!=0) return -1;
1797
+		if(str_append(&ob, &bsuffix, &b)!=0) {
1798
+			LM_ERR("Can't append suffix to boundary\n");
1799
+			goto error;
1800
+		}
1801
+		if(str_append(&ob, &fsuffix,&fb)!=0) {
1802
+			LM_ERR("Can't append suffix to final boundary\n");
1803
+			goto error;
1804
+		}
1805
+		ret = b.len-2;
1806
+		while(t>0)
1807
+		{
1808
+			if(find_line_start(b.s, ret, &tmp.s,
1809
+				(unsigned int *)&tmp.len))
1810
+			{
1811
+				/*LM_DBG("found t[%d] tmp.len[%d]:[%.*s]\n",
1812
+					t, tmp.len, tmp.len, tmp.s);*/
1813
+				if(!lb)
1814
+				{
1815
+					lb = pkg_malloc(sizeof(struct str_list));
1816
+					if (!lb) {
1817
+						PKG_MEM_ERROR;
1818
+						goto error;
1819
+					}
1820
+					lb->s.s = tmp.s;
1821
+					lb->s.len = tmp.len;
1822
+					lb->next = 0;
1823
+					lb_t = lb;
1824
+				}
1825
+				else
1826
+				{
1827
+					lb_t = append_str_list(tmp.s, tmp.len, &lb_t, &lb_size);
1828
+				}
1829
+				lb_found = lb_found + 1;
1830
+				tmp.s = tmp.s + ret;
1831
+				t =  t - ret;
1832
+				tmp.len = tmp.len - ret;
1833
+			}
1834
+			else { t=0; }
1835
+		}
1836
+		if(lb_found<2)
1837
+		{
1838
+			LM_ERR("found[%d] wrong number of boundaries\n", lb_found);
1839
+			goto error;
1840
+		}
1841
+		/* adding 2 chars in advance */
1842
+		body.len = buf.len + 2;
1843
+		body.s = pkg_malloc(sizeof(char)*body.len);
1844
+		if (!body.s) {
1845
+			PKG_MEM_ERROR;
1846
+			goto error;
1847
+		}
1848
+		pb = body.s; body.len = 0;
1849
+		lb_t = lb;
1850
+		while(lb_t)
1851
+		{
1852
+			tmp.s = lb_t->s.s; tmp.len = lb_t->s.len;
1853
+			tmp.len = get_line(lb_t->s);
1854
+			if(tmp.len!=b.len || strncmp(b.s, tmp.s, b.len)!=0)
1855
+			{
1856
+				LM_DBG("malformed bondary in the middle\n");
1857
+				memcpy(pb, b.s, b.len); body.len = body.len + b.len;
1858
+				pb = pb + b.len;
1859
+				t = lb_t->s.s - (lb_t->s.s + tmp.len);
1860
+				memcpy(pb, lb_t->s.s+tmp.len, t); pb = pb + t;
1861
+				/*LM_DBG("new chunk[%d][%.*s]\n", t, t, pb-t);*/
1862
+			}
1863
+			else {
1864
+				t = lb_t->next->s.s - lb_t->s.s;
1865
+				memcpy(pb, lb_t->s.s, t);
1866
+				/*LM_DBG("copy[%d][%.*s]\n", t, t, pb);*/
1867
+				pb = pb + t;
1868
+			}
1869
+			body.len = body.len + t;
1870
+			/*LM_DBG("body[%d][%.*s]\n", body.len, body.len, body.s);*/
1871
+			lb_t = lb_t->next;
1872
+			if(!lb_t->next) lb_t = NULL;
1873
+		}
1874
+		/* last boundary */
1875
+		tmp.s = lb->s.s; tmp.len = lb->s.len;
1876
+		tmp.len = get_line(lb->s);
1877
+		if(tmp.len!=fb.len || strncmp(fb.s, tmp.s, fb.len)!=0)
1878
+		{
1879
+			LM_DBG("last bondary without -- at the end\n");
1880
+			memcpy(pb, fb.s, fb.len);
1881
+			/*LM_DBG("new chunk[%d][%.*s]\n", fb.len, fb.len, pb);*/
1882
+			pb = pb + fb.len;
1883
+			body.len = body.len + fb.len;
1884
+		}
1885
+		else {
1886
+			memcpy(pb, lb->s.s, lb->s.len); pb = pb + lb->s.len;
1887
+			body.len = body.len + lb->s.len;
1888
+			/*LM_DBG("copy[%d][%.*s]\n", lb->s.len, lb->s.len, pb - lb->s.len);*/
1889
+		}
1890
+		/*LM_DBG("body[%d][%.*s] expected[%ld]\n",
1891
+			body.len, body.len, body.s, pb-body.s); */
1892
+		if(!replace_body(msg, body))
1893
+		{
1894
+			LM_ERR("Can't replace body\n");
1895
+			goto error;
1896
+		}
1897
+		msg->msg_flags &= ~FL_BODY_MULTIPART;
1898
+		ret = 1;
1899
+		goto clean;
1900
+	}
1623 1901
 
1902
+error:
1903
+	ret = -1;
1904
+clean:
1905
+	if(ob.s) pkg_free(ob.s);
1906
+	if(b.s) pkg_free(b.s);
1907
+	if(fb.s) pkg_free(fb.s);
1908
+	if(body.s) pkg_free(body.s);
1909
+	if(buf.s) pkg_free(buf.s);
1910
+	while(lb)
1911
+	{
1912
+		lb_t = lb->next;
1913
+		pkg_free(lb);
1914
+		lb = lb_t;
1915
+	}
1916
+	return ret;
1917
+}
1624 1918
 
1625 1919
 /** builds a request in memory from another sip request.
1626 1920
   *
... ...
@@ -1700,6 +1995,9 @@ char * build_req_buf_from_sip_req( struct sip_msg* msg,
1700 1700
 	path_buf.len=0;
1701 1701
 
1702 1702
 	flags=msg->msg_flags|global_req_flags;
1703
+	if(check_boundaries(msg, send_info)<0){
1704
+		LM_WARN("check_boundaries error\n");
1705
+	}
1703 1706
 	/* Calculate message body difference and adjust Content-Length */
1704 1707
 	body_delta = lumps_len(msg, msg->body_lumps, send_info);
1705 1708
 	if (adjust_clen(msg, body_delta, send_info->proto) < 0) {
... ...
@@ -1956,8 +2254,6 @@ error00:
1956 1956
 	return 0;
1957 1957
 }
1958 1958
 
1959
-
1960
-
1961 1959
 char * generate_res_buf_from_sip_res( struct sip_msg* msg,
1962 1960
 				unsigned int *returned_len, unsigned int mode)
1963 1961
 {
... ...
@@ -162,4 +162,7 @@ void fix_global_req_flags(str* gname, str* name);
162 162
 
163 163
 int build_sip_msg_from_buf(struct sip_msg *msg, char *buf, int len,
164 164
 		unsigned int id);
165
+
166
+/* returns a copy in private memory of the boundary in a multipart body */
167
+int get_boundary(struct sip_msg* msg, str* boundary);
165 168
 #endif