@@ -1580,6 +1580,7 @@ static int check_hostname(str *domain)
15801580#define MAX_REASON 256
15811581
15821582enum 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+
16151687static 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