Skip to content

Commit 9be7fa9

Browse files
davidtrihy-genesysbenceszigeti
authored andcommitted
Contact validation for REGISTER and UPDATE for sipmsg_validate
1 parent acce770 commit 9be7fa9

File tree

1 file changed

+87
-36
lines changed

1 file changed

+87
-36
lines changed

modules/sipmsgops/sipmsgops.c

Lines changed: 87 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1580,6 +1580,7 @@ static int check_hostname(str *domain)
15801580
#define MAX_REASON 256
15811581

15821582
enum sip_validation_failures {
1583+
SV_NO_ERROR=0,
15831584
SV_NO_MSG=-1,
15841585
SV_HDR_PARSE_ERROR=-2,
15851586
SV_NO_CALLID=-3,
@@ -1609,18 +1610,86 @@ enum sip_validation_failures {
16091610
SV_BAD_USERNAME=-27,
16101611
SV_FROM_USERNAME_ERROR=-28,
16111612
SV_TO_USERNAME_ERROR=-29,
1613+
SV_BAD_EXPIRES=-30,
16121614
SV_GENERIC_FAILURE=-255
16131615
};
16141616

1617+
#define METHOD_WITH_CONTACT_HDR (METHOD_INVITE | METHOD_REGISTER | METHOD_UPDATE | METHOD_SUBSCRIBE | METHOD_REFER)
1618+
1619+
static enum sip_validation_failures validate_contact_header(struct sip_msg *msg, enum request_method method, char reason[static MAX_REASON])
1620+
{
1621+
struct hdr_field *ptr = NULL, *expires = NULL;
1622+
contact_t * contacts = NULL;
1623+
contact_body_t *contact_body = NULL;
1624+
exp_body_t *expires_body = NULL;
1625+
struct sip_uri test_contacts;
1626+
enum sip_validation_failures ret;
1627+
1628+
if (method & METHOD_WITH_CONTACT_HDR) {
1629+
ret = SV_NO_CONTACT;
1630+
CHECK_HEADER("", contact);
1631+
1632+
/* iterate through Contact headers */
1633+
for(ptr = msg->contact; ptr; ptr = ptr->sibling) {
1634+
/* parse Contact header */
1635+
if(!ptr->parsed && (parse_contact(ptr) < 0
1636+
|| !ptr->parsed)) {
1637+
strcpy(reason, "failed to parse 'Contact' header");
1638+
ret = SV_CONTACT_PARSE_ERROR;
1639+
goto failed;
1640+
}
1641+
contacts = ((contact_body_t*)ptr->parsed)->contacts;
1642+
1643+
if (contacts != NULL) {
1644+
/* iterate through URIs and check validty */
1645+
for (; contacts; contacts = contacts->next) {
1646+
if(parse_uri(contacts->uri.s, contacts->uri.len,
1647+
&test_contacts) < 0
1648+
|| test_contacts.host.len < 0) {
1649+
strcpy(reason, "failed to parse 'Contact' header");
1650+
ret = SV_CONTACT_PARSE_ERROR;
1651+
goto failed;
1652+
}
1653+
}
1654+
} else {
1655+
/* empty contacts header - this can be a * Contact header, valid only for REGISTER requests */
1656+
contact_body = (contact_body_t *) msg->contact->parsed;
1657+
1658+
if (method != METHOD_REGISTER || msg->first_line.type == SIP_REPLY) {
1659+
strcpy(reason, "empty body for 'Contact' header");
1660+
ret = SV_CONTACT_PARSE_ERROR;
1661+
goto failed;
1662+
} else {
1663+
if (!msg->expires || (parse_expires(msg->expires) < 0 || !msg->expires->parsed)) {
1664+
strcpy(reason, "failed to parse 'Expires' header");
1665+
ret = SV_BAD_EXPIRES;
1666+
goto failed;
1667+
}
1668+
1669+
expires_body = (exp_body_t*) msg->expires->parsed;
1670+
1671+
if (!expires_body || !(expires_body->val == 0 && contact_body->star == 1)) {
1672+
strcpy(reason, "Expires header greater than 0 for REGISTER 'Contact' header with '*' value");
1673+
ret = SV_CONTACT_PARSE_ERROR;
1674+
goto failed;
1675+
}
1676+
}
1677+
}
1678+
}
1679+
}
1680+
1681+
ret = SV_NO_ERROR;
1682+
1683+
failed:
1684+
return ret;
1685+
}
1686+
16151687
static int w_sip_validate(struct sip_msg *msg, void *_flags, pv_spec_t* err_txt)
16161688
{
1617-
unsigned int hdrs_len;
1689+
unsigned int hdrs_len, status_code;
16181690
unsigned long flags = (unsigned long)_flags;
16191691
int method;
16201692
str body;
1621-
struct hdr_field * ptr;
1622-
contact_t * contacts;
1623-
struct sip_uri test_contacts;
16241693
struct sip_uri *p_uri;
16251694
struct cseq_body * cbody;
16261695
pv_value_t pv_val;
@@ -1784,38 +1853,11 @@ static int w_sip_validate(struct sip_msg *msg, void *_flags, pv_spec_t* err_txt)
17841853
CHECK_HEADER("", maxforwards);
17851854
}
17861855

1787-
if (msg->REQ_METHOD == METHOD_INVITE) {
1788-
ret = SV_NO_CONTACT;
1789-
CHECK_HEADER("INVITE", contact);
1790-
if(flags & SIP_PARSE_CONTACT) {
1791-
/* iterate through Contact headers */
1792-
for(ptr = msg->contact; ptr; ptr = ptr->sibling) {
1793-
/* parse Contact header */
1794-
if(!ptr->parsed && (parse_contact(ptr) < 0
1795-
|| !ptr->parsed)) {
1796-
strcpy(reason, "failed to parse 'Contact' header");
1797-
ret = SV_CONTACT_PARSE_ERROR;
1798-
goto failed;
1799-
}
1800-
contacts = ((contact_body_t*)ptr->parsed)->contacts;
1801-
/* empty contacts header - something must be wrong */
1802-
if(contacts == NULL) {
1803-
strcpy(reason, "empty body for 'Contact' header");
1804-
ret = SV_CONTACT_PARSE_ERROR;
1805-
goto failed;
1806-
}
1807-
/* iterate through URIs and check validty */
1808-
for(; contacts; contacts = contacts->next) {
1809-
if(parse_uri(contacts->uri.s, contacts->uri.len,
1810-
&test_contacts) < 0
1811-
|| test_contacts.host.len < 0) {
1812-
strcpy(reason, "failed to parse 'Contact' header");
1813-
ret = SV_CONTACT_PARSE_ERROR;
1814-
goto failed;
1815-
}
1816-
}
1817-
}
1856+
if (flags & SIP_PARSE_CONTACT) {
1857+
ret = validate_contact_header(msg, msg->REQ_METHOD, reason);
18181858

1859+
if (ret != SV_NO_ERROR) {
1860+
goto failed;
18191861
}
18201862
}
18211863

@@ -1838,8 +1880,9 @@ static int w_sip_validate(struct sip_msg *msg, void *_flags, pv_spec_t* err_txt)
18381880
goto failed;
18391881
}
18401882
method = cbody->method_id;
1883+
status_code = msg->first_line.u.reply.statuscode;
18411884
if (method != METHOD_CANCEL) {
1842-
switch (msg->first_line.u.reply.statuscode) {
1885+
switch (status_code) {
18431886
case 405:
18441887
ret = SV_NOALLOW_405;
18451888
CHECK_HEADER("", allow);
@@ -1869,6 +1912,14 @@ static int w_sip_validate(struct sip_msg *msg, void *_flags, pv_spec_t* err_txt)
18691912
}
18701913
}
18711914

1915+
if (flags & SIP_PARSE_CONTACT && (status_code > 199 || status_code < 400)) {
1916+
ret = validate_contact_header(msg, method, reason);
1917+
1918+
if (ret != 0) {
1919+
goto failed;
1920+
}
1921+
}
1922+
18721923
break;
18731924

18741925
default:

0 commit comments

Comments
 (0)