Commit 75bf5577 authored by jehan's avatar jehan

add uri checking

parent a6bd4f88
......@@ -3,7 +3,7 @@
AC_PREREQ([2.63])
AC_INIT([belle-sip],[1.2.3],[jehan.monnier@linphone.org])
AC_INIT([belle-sip],[1.2.4],[jehan.monnier@linphone.org])
AC_CONFIG_SRCDIR([src/belle_sip_utils.c])
......
......@@ -53,7 +53,7 @@ BELLESIP_EXPORT belle_sip_request_t* belle_sip_request_create(belle_sip_uri_t *r
BELLESIP_EXPORT belle_sip_uri_t* belle_sip_request_get_uri(belle_sip_request_t* request);
BELLESIP_EXPORT belle_sip_uri_t* belle_sip_request_get_uri(const belle_sip_request_t* request);
BELLESIP_EXPORT void belle_sip_request_set_uri(belle_sip_request_t* request, belle_sip_uri_t* uri);
BELLESIP_EXPORT const char* belle_sip_request_get_method(const belle_sip_request_t* request);
BELLESIP_EXPORT void belle_sip_request_set_method(belle_sip_request_t* request,const char* method);
......@@ -138,6 +138,13 @@ BELLESIP_EXPORT int belle_sip_response_fix_contact(const belle_sip_response_t* r
**/
BELLESIP_EXPORT int belle_sip_message_check_headers(const belle_sip_message_t* message);
/**
* check uri components of headers and req uri.
* return 0 if not compliant
* */
BELLESIP_EXPORT int belle_sip_request_check_uris_components(const belle_sip_request_t* request);
BELLE_SIP_END_DECLS
#endif
......
......@@ -201,7 +201,14 @@ belle_sip_error_code belle_sip_uri_marshal(const belle_sip_uri_t* uri, char* buf
*
* */
BELLESIP_EXPORT int belle_sip_uri_equals(const belle_sip_uri_t* uri_a,const belle_sip_uri_t* uri_b);
/**
* returns 0 if uri does follows components requirement for being a request uri
* */
BELLESIP_EXPORT int belle_sip_uri_check_components_from_request_uri(const belle_sip_uri_t* uri);
/**
* returns 0 if uri does follows components requirement for a given method/header
*/
BELLESIP_EXPORT int belle_sip_uri_check_components_from_context(const belle_sip_uri_t* uri,const char* method,const char* header_name);
BELLE_SIP_END_DECLS
......
......@@ -329,18 +329,31 @@ belle_sip_error_code belle_sip_header_from_marshal(belle_sip_header_from_t* from
BELLE_SIP_FROM_LIKE_MARSHAL(from);
}
belle_sip_header_from_t* belle_sip_header_from_create2(const char *address, const char *tag){
char *tmp=belle_sip_strdup_printf("From: %s",address);
belle_sip_header_from_t *from=belle_sip_header_from_parse(tmp);
if (from){
if (tag) belle_sip_header_from_set_tag(from,tag);
}
belle_sip_free(tmp);
return from;
belle_sip_header_from_t* belle_sip_header_from_create2(const char *uri, const char *tag){
belle_sip_header_address_t* address = belle_sip_header_address_parse(uri);
if (address) {
belle_sip_header_from_t* from = belle_sip_header_from_create(address,tag);
belle_sip_object_unref(address);
return from;
} else
return NULL;
}
belle_sip_header_from_t* belle_sip_header_from_create(const belle_sip_header_address_t* address, const char *tag) {
belle_sip_header_from_t* header= belle_sip_header_from_new();
belle_sip_uri_t* uri;
_belle_sip_object_copy((belle_sip_object_t*)header,(belle_sip_object_t*)address);
/*clear unwanted uri components*/
if ((uri=belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(header)))) {
belle_sip_parameters_t* params=BELLE_SIP_PARAMETERS(uri);
belle_sip_parameters_remove_parameter(params,"lr");
belle_sip_parameters_remove_parameter(params,"ttl");
belle_sip_parameters_remove_parameter(params,"method");
belle_sip_parameters_remove_parameter(params,"maddr");
belle_sip_parameters_remove_parameter(params,"transport");
belle_sip_uri_set_port(uri,-1);
belle_sip_uri_headers_clean(uri);
}
belle_sip_header_set_name(BELLE_SIP_HEADER(header),BELLE_SIP_FROM); /*restore header name*/
if (tag) belle_sip_header_from_set_tag(header,tag);
return header;
......@@ -385,18 +398,30 @@ BELLE_SIP_NEW_HEADER(header_to,header_address,BELLE_SIP_TO)
BELLE_SIP_PARSE(header_to)
GET_SET_STRING_PARAM2(belle_sip_header_to,tag,raw_tag);
belle_sip_header_to_t* belle_sip_header_to_create2(const char *address, const char *tag){
char *tmp=belle_sip_strdup_printf("To: %s",address);
belle_sip_header_to_t *to=belle_sip_header_to_parse(tmp);
if (to){
if (tag) belle_sip_header_to_set_tag(to,tag);
}
belle_sip_free(tmp);
return to;
belle_sip_header_to_t* belle_sip_header_to_create2(const char *uri, const char *tag){
belle_sip_header_address_t* address = belle_sip_header_address_parse(uri);
if (address) {
belle_sip_header_to_t* to = belle_sip_header_to_create(address,tag);
belle_sip_object_unref(address);
return to;
} else
return NULL;
}
belle_sip_header_to_t* belle_sip_header_to_create(const belle_sip_header_address_t* address, const char *tag) {
belle_sip_header_to_t* header= belle_sip_header_to_new();
belle_sip_uri_t* uri;
_belle_sip_object_copy((belle_sip_object_t*)header,(belle_sip_object_t*)address);
/*clear unwanted uri components*/
if ((uri=belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(header)))) {
belle_sip_parameters_t* params=BELLE_SIP_PARAMETERS(uri);
belle_sip_parameters_remove_parameter(params,"lr");
belle_sip_parameters_remove_parameter(params,"ttl");
belle_sip_parameters_remove_parameter(params,"method");
belle_sip_parameters_remove_parameter(params,"maddr");
belle_sip_parameters_remove_parameter(params,"transport");
belle_sip_uri_set_port(uri,-1);
belle_sip_uri_headers_clean(uri);
}
belle_sip_header_set_name(BELLE_SIP_HEADER(header),BELLE_SIP_TO); /*restaure header name*/
if (tag) belle_sip_header_to_set_tag(header,tag);
return header;
......
......@@ -427,12 +427,12 @@ typedef struct uri_components {
} uri_components_t;
/*belle sip allows contact header without host because stack will auutomatically put host if missing*/
static uri_components_t uri_component_use_for_request = {"Req.-URI" ,o ,o ,m ,o ,o ,na ,o ,o ,o ,o ,o ,na};
static uri_components_t uri_component_use_for_header_to = {"Header To" ,o ,o ,m ,na ,o ,na ,na ,na ,na ,na ,o ,na};
static uri_components_t uri_component_use_for_header_from = {"Header From" ,o ,o ,m ,na ,o ,na ,na ,na ,na ,na ,o ,na};
static uri_components_t uri_component_use_for_contact_in_reg = {"Contact in REG" ,o ,o ,m ,o ,o ,na ,o ,o ,o ,na ,o ,na};
static uri_components_t uri_component_use_for_dialog_ct_rr_ro = {"Dialog Contact/R-R/Route" ,o ,o ,m ,o ,o ,na ,o ,o ,o ,na ,o ,na};
static uri_components_t uri_component_use_for_contact_in_reg = {"Contact in REG" ,o ,o ,/*m*/o ,o ,o ,na ,o ,o ,o ,na ,o ,o};
static uri_components_t uri_component_use_for_dialog_ct_rr_ro = {"Dialog Contact/R-R/Route" ,o ,o ,/*m*/o ,o ,o ,na ,o ,na ,o ,o ,o ,na};
static uri_components_t uri_component_use_for_external = {"External" ,o ,o ,m ,o ,o ,o ,o ,o ,o ,o ,o ,o};
......@@ -453,36 +453,36 @@ if (!check_component(uri_component,component_use_rule)) {\
static int check_uri_components(const belle_sip_uri_t* uri, const uri_components_t* components_use) {
CHECK_URI_COMPONENT(uri->user==NULL,"user",components_use->user,components_use->name)
CHECK_URI_COMPONENT(uri->host==NULL,"host",components_use->host,components_use->name)
CHECK_URI_COMPONENT(uri->user!=NULL,"user",components_use->user,components_use->name)
CHECK_URI_COMPONENT(uri->host!=NULL,"host",components_use->host,components_use->name)
CHECK_URI_COMPONENT(uri->port>0,"port",components_use->port,components_use->name)
CHECK_URI_COMPONENT(belle_sip_parameters_has_parameter(&uri->params,"maddr"),"maddr-param",components_use->maddr_param,components_use->name)
CHECK_URI_COMPONENT(belle_sip_parameters_has_parameter(&uri->params,"ttl"),"ttl-param",components_use->ttl_param,components_use->name)
CHECK_URI_COMPONENT(belle_sip_parameters_has_parameter(&uri->params,"transport"),"transp.-param",components_use->transp_param,components_use->name)
CHECK_URI_COMPONENT(belle_sip_parameters_has_parameter(&uri->params,"lr"),"lr-param",components_use->lr_param,components_use->name)
/*..*/
CHECK_URI_COMPONENT(uri->header_list==NULL,"headers",components_use->headers,components_use->name)
CHECK_URI_COMPONENT(belle_sip_list_size(belle_sip_parameters_get_parameters(uri->header_list))>0,"headers",components_use->headers,components_use->name)
return TRUE;
}
/*return 0 if not compliant*/
int check_uri_components_from_request_uri(const belle_sip_uri_t* uri) {
return !check_uri_components(uri,&uri_component_use_for_request);
int belle_sip_uri_check_components_from_request_uri(const belle_sip_uri_t* uri) {
return check_uri_components(uri,&uri_component_use_for_request);
}
int check_uri_components_from_context(const belle_sip_uri_t* uri,const char* method,const char* header_name) {
int belle_sip_uri_check_components_from_context(const belle_sip_uri_t* uri,const char* method,const char* header_name) {
if (strcasecmp(BELLE_SIP_FROM,header_name)==0)
return !check_uri_components(uri,&uri_component_use_for_header_from);
return check_uri_components(uri,&uri_component_use_for_header_from);
else if (strcasecmp(BELLE_SIP_TO,header_name)==0)
return !check_uri_components(uri,&uri_component_use_for_header_to);
else if (strcasecmp(BELLE_SIP_CONTACT,header_name)==0 && strcasecmp("REGISTER",header_name)==0)
return !check_uri_components(uri,&uri_component_use_for_contact_in_reg);
return check_uri_components(uri,&uri_component_use_for_header_to);
else if (strcasecmp(BELLE_SIP_CONTACT,header_name)==0 && method && strcasecmp("REGISTER",method)==0)
return check_uri_components(uri,&uri_component_use_for_contact_in_reg);
else if (strcasecmp(BELLE_SIP_CONTACT,header_name)==0
|| strcasecmp(BELLE_SIP_RECORD_ROUTE,header_name)==0
|| strcasecmp(BELLE_SIP_ROUTE,header_name)==0)
return !check_uri_components(uri,&uri_component_use_for_dialog_ct_rr_ro);
return check_uri_components(uri,&uri_component_use_for_dialog_ct_rr_ro);
else
return !check_uri_components(uri,&uri_component_use_for_external);
return check_uri_components(uri,&uri_component_use_for_external);
}
......@@ -320,7 +320,7 @@ void belle_sip_request_set_uri(belle_sip_request_t* request,belle_sip_uri_t* uri
request->uri=uri;
}
belle_sip_uri_t * belle_sip_request_get_uri(belle_sip_request_t *request){
belle_sip_uri_t * belle_sip_request_get_uri(const belle_sip_request_t *request){
return request->uri;
}
......@@ -863,3 +863,21 @@ int belle_sip_message_check_headers(const belle_sip_message_t* message) {
return 1;
}
int belle_sip_request_check_uris_components(const belle_sip_request_t* request) {
belle_sip_list_t* iterator = belle_sip_message_get_all_headers(BELLE_SIP_MESSAGE(request));
for (;iterator!=NULL;iterator=iterator->next) {
belle_sip_header_t* header=(belle_sip_header_t*)iterator->data;
if (BELLE_SIP_IS_INSTANCE_OF(header,belle_sip_header_address_t)) {
belle_sip_uri_t* uri=belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(header));
if (uri && !belle_sip_uri_check_components_from_context(uri,belle_sip_request_get_method(request),belle_sip_header_get_name(header))) {
char* header_string=belle_sip_object_to_string(header);
belle_sip_error("Malformed header [%s] for request [%p]",header_string,request);
belle_sip_free(header_string);
return FALSE;
}
}
}
return belle_sip_uri_check_components_from_request_uri(belle_sip_request_get_uri((const belle_sip_request_t*)request));
}
......@@ -330,6 +330,11 @@ int belle_sip_client_transaction_send_request_to(belle_sip_client_transaction_t
return -1;
}
/*check uris components compliance*/
if (!belle_sip_request_check_uris_components(t->base.request)) {
belle_sip_error("belle_sip_client_transaction_send_request: bad request for transaction [%p]",t);
return -1;
}
/*store preset route for future use by refresher*/
if (outbound_proxy){
t->preset_route=outbound_proxy;
......
......@@ -103,10 +103,18 @@ static void test_from_header(void) {
belle_sip_object_unref(BELLE_SIP_OBJECT(L_from));
/*test factory*/
L_from = belle_sip_header_from_create2("super <sip:titi.com>","12345-abc");
L_from = belle_sip_header_from_create2("super <sip:titi.com:5060;lr;ttl=1;method=INVITE;maddr=192.168.0.1;transport=tcp?header=123>","12345-abc");
CU_ASSERT_PTR_NOT_NULL_FATAL(L_from);
L_uri = belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(L_from));
CU_ASSERT_PTR_NOT_NULL_FATAL(L_uri);
CU_ASSERT_FALSE(belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(L_uri),"lr"));
CU_ASSERT_FALSE(belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(L_uri),"ttl"));
CU_ASSERT_FALSE(belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(L_uri),"method"));
CU_ASSERT_FALSE(belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(L_uri),"maddr"));
CU_ASSERT_FALSE(belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(L_uri),"transport"));
CU_ASSERT_FALSE(belle_sip_uri_get_port(L_uri)>0);
CU_ASSERT_EQUAL(belle_sip_list_size(belle_sip_uri_get_header_names(L_uri)),0);
CU_ASSERT_STRING_EQUAL(belle_sip_uri_get_host(L_uri), "titi.com");
CU_ASSERT_STRING_EQUAL(belle_sip_header_from_get_tag(L_from),"12345-abc");
belle_sip_object_unref(L_from);
......@@ -147,9 +155,17 @@ static void test_to_header(void) {
CU_ASSERT_STRING_EQUAL(belle_sip_header_to_get_tag(L_to),"dlfjklcn6545614XX");
belle_sip_object_unref(BELLE_SIP_OBJECT(L_to));
/*test factory*/
L_to = belle_sip_header_to_create2("\"super man\" <sip:titi.com>","12345-abc");
L_to = belle_sip_header_to_create2("\"super man\" <sip:titi.com:5060;lr;ttl=1;method=INVITE;maddr=192.168.0.1;transport=tcp?header=123>","12345-abc");
CU_ASSERT_PTR_NOT_NULL_FATAL(L_to);
L_uri = belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(L_to));
CU_ASSERT_FALSE(belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(L_uri),"lr"));
CU_ASSERT_FALSE(belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(L_uri),"ttl"));
CU_ASSERT_FALSE(belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(L_uri),"method"));
CU_ASSERT_FALSE(belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(L_uri),"maddr"));
CU_ASSERT_FALSE(belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(L_uri),"transport"));
CU_ASSERT_FALSE(belle_sip_uri_get_port(L_uri)>0);
CU_ASSERT_EQUAL(belle_sip_list_size(belle_sip_uri_get_header_names(L_uri)),0);
CU_ASSERT_PTR_NOT_NULL_FATAL(L_uri);
CU_ASSERT_STRING_EQUAL(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(L_to)), "super man");
CU_ASSERT_STRING_EQUAL(belle_sip_header_to_get_tag(L_to),"12345-abc");
......
......@@ -541,6 +541,26 @@ static void testUriHeadersInInvite(void) {
belle_sip_object_unref(request);
}
static void testUrisComponentsForRequest(void) {
belle_sip_request_t* request;
belle_sip_stack_t *stack=belle_sip_stack_new(NULL);
belle_sip_provider_t *prov=belle_sip_provider_new(stack,NULL);
belle_sip_client_transaction_t* t;
const char* raw_uri="sip:toto@titi.com?header1=blabla";
request=belle_sip_request_create( belle_sip_uri_parse(raw_uri)
,"INVITE"
,belle_sip_provider_create_call_id(prov)
,belle_sip_header_cseq_create(20,"INVITE")
,belle_sip_header_from_create2("sip:toto@titi.com","4654")
,belle_sip_header_to_parse("To: sip:titi@titi.com:5061")
,belle_sip_header_via_new()
,70);
CU_ASSERT_PTR_NOT_NULL(request);
t=belle_sip_provider_create_client_transaction(prov,request);
CU_ASSERT_NOT_EQUAL(belle_sip_client_transaction_send_request(t),0);
}
/* NOTE - ORDER IS IMPORTANT - MUST TEST fread() AFTER fprintf() */
test_t message_tests[] = {
{ "REGISTER", testRegisterMessage },
......@@ -556,7 +576,8 @@ test_t message_tests[] = {
{ "Channel parser error recovery", channel_parser_tester_recovery_from_error},
{ "Channel parser malformed start", channel_parser_malformed_start},
{ "RFC2543 compatibility", testRFC2543Compat},
{ "Uri headers in sip INVITE",testUriHeadersInInvite}
{ "Uri headers in sip INVITE",testUriHeadersInInvite},
{ "Uris components in request",testUrisComponentsForRequest}
};
test_suite_t message_test_suite = {
......
......@@ -335,6 +335,55 @@ static void test_uri_equals(void) {
}
/*
* From 19.1.1 SIP and SIPS URI Components
* dialog
reg./redir. Contact/
default Req.-URI To From Contact R-R/Route external
user -- o o o o o o
password -- o o o o o o
host -- m m m m m m
port (1) o - - o o o
user-param ip o o o o o o
method INVITE - - - - - o
maddr-param -- o - - o o o
ttl-param 1 o - - o - o
transp.-param (2) o - - o o o
lr-param -- o - - - o o
other-param -- o o o o o o
headers -- - - - o - o*/
void testUriComponentsChecker() {
belle_sip_uri_t* uri = belle_sip_uri_parse("sip:hostonly");
CU_ASSERT_TRUE(belle_sip_uri_check_components_from_request_uri(uri));
belle_sip_object_unref(uri);
{
belle_sip_header_from_t* header = belle_sip_header_from_parse("From: sip:linphone.org:5061");
CU_ASSERT_FALSE(belle_sip_uri_check_components_from_context(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(header)),NULL,"From"));
belle_sip_object_unref(header);
}
{
belle_sip_header_to_t* header = belle_sip_header_to_parse("To: sip:linphone.org?header=interdit");
CU_ASSERT_FALSE(belle_sip_uri_check_components_from_context(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(header)),NULL,"To"));
belle_sip_object_unref(header);
}
{
belle_sip_header_contact_t* header = belle_sip_header_contact_parse("Contact: <sip:linphone.org;lr>");
CU_ASSERT_FALSE(belle_sip_uri_check_components_from_context(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(header)),"REGISTER","Contact"));
CU_ASSERT_TRUE(belle_sip_uri_check_components_from_context(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(header)),NULL,"Contact"));
belle_sip_object_unref(header);
}
{
belle_sip_header_record_route_t* header = belle_sip_header_record_route_parse("Record-Route: <sip:linphone.org;ttl=interdit>");
CU_ASSERT_FALSE(belle_sip_uri_check_components_from_context(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(header)),NULL,"Record-Route"));
belle_sip_object_unref(header);
}
{
belle_sip_uri_t* uri = belle_sip_uri_parse("sip:linphone.org:5061?header=toto");
CU_ASSERT_TRUE(belle_sip_uri_check_components_from_context(uri,NULL,"Any"));
belle_sip_object_unref(uri);
}
}
test_t uri_tests[] = {
{ "Simple URI", testSIMPLEURI },
......@@ -350,7 +399,8 @@ test_t uri_tests[] = {
{ "SIPS URI", testSIPSURI },
{ "URI equals", test_uri_equals },
{ "Simple URI error", testSIMPLEURI_error },
{ "IPv6 URI", testIPV6URI }
{ "IPv6 URI", testIPV6URI },
{ "URI components", testUriComponentsChecker }
};
test_suite_t uri_test_suite = {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment