Commit 9a922e7c authored by jehan's avatar jehan

copy uri headers in request

parent 225f9e3d
......@@ -37,6 +37,15 @@ BELLESIP_EXPORT belle_sip_uri_t* belle_sip_uri_create (const char* username,cons
*
*/
BELLESIP_EXPORT const char* belle_sip_uri_get_header(const belle_sip_uri_t* uri,const char* name);
/**
* remove all headers
*
*/
BELLESIP_EXPORT void belle_sip_uri_headers_clean(belle_sip_uri_t* uri);
/**
* Returns an Iterator over the const char*names of all headers present in this SipURI.
*
......
......@@ -211,6 +211,14 @@ SIP_URI_GET_SET_INT_PARAM(ttl)
SIP_URI_HAS_SET_BOOL_PARAM(lr)
const belle_sip_parameters_t* belle_sip_uri_get_headers(const belle_sip_uri_t* uri) {
return uri->header_list;
}
void belle_sip_uri_headers_clean(belle_sip_uri_t* uri) {
belle_sip_parameters_clean(uri->header_list);
}
static int uri_strncmp_common(const char*a,const char*b,size_t n,int case_sensitive) {
......@@ -355,3 +363,126 @@ int belle_sip_uri_equals(const belle_sip_uri_t* uri_a,const belle_sip_uri_t* uri
return 1;
}
/*uri checker*/
/*
* 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
(1): The default port value is transport and scheme dependent. The
default is 5060 for sip: using UDP, TCP, or SCTP. The default is
5061 for sip: using TLS over TCP and sips: over TCP.
(2): The default transport is scheme dependent. For sip:, it is UDP.
For sips:, it is TCP.
Table 1: Use and default values of URI components for SIP header
field values, Request-URI and references*/
typedef enum {
m /*mandotory*/
, o /*optionnal*/
, na /*not allowd*/
} mark;
static const char* mark_to_string(mark value) {
switch (value) {
case o: return "optionnal";
case m: return "mandatory";
case na: return "not allowed";
}
return "unknown";
}
typedef struct uri_components {
const char * name;
mark user;
mark password;
mark host;
mark port;
mark user_param;
mark method;
mark maddr_param;
mark ttl_param;
mark transp_param;
mark lr_param;
mark other_param;
mark headers;
} uri_components_t;
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_external = {"External" ,o ,o ,m ,o ,o ,o ,o ,o ,o ,o ,o ,o};
static int check_component(int is_present,mark requirement) {
switch (requirement) {
case o: return TRUE;
case m: return is_present;
case na: return !is_present;
}
return 0;
}
#define CHECK_URI_COMPONENT(uri_component,uri_component_name,component_use_rule,component_use_rule_name) \
if (!check_component(uri_component,component_use_rule)) {\
belle_sip_error("Uri component [%s] does not follow reqs [%s] for context [%s]", uri_component_name,mark_to_string(component_use_rule),component_use_rule_name);\
return FALSE;\
}
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->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)
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 check_uri_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);
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);
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);
else
return !check_uri_components(uri,&uri_component_use_for_external);
}
......@@ -502,6 +502,26 @@ BELLE_SIP_PARSE(response)
GET_SET_STRING(belle_sip_response,reason_phrase);
GET_SET_INT(belle_sip_response,status_code,int)
static int is_authorized_uri_header(const char* header_name) {
/*From, Call-ID, CSeq, Via, and Record-Route*/
/*Accept, Accept-Encoding, Accept-Language, Allow,
Contact (in its dialog usage), Organization, Supported, and User-Agent*/
return (strcasecmp("From",header_name) != 0
&& strcasecmp("Call-ID",header_name) != 0
&& strcasecmp("CSeq",header_name) != 0
&& strcasecmp("Via",header_name) != 0
&& strcasecmp("Record-Route",header_name) != 0
&& strcasecmp("Accept",header_name) != 0
&& strcasecmp("Accept-Encoding",header_name) != 0
&& strcasecmp("Accept-Language",header_name) != 0
&& strcasecmp("Allow",header_name) != 0
&& strcasecmp("Contact",header_name) != 0
&& strcasecmp("Organization",header_name) != 0
&& strcasecmp("Supported",header_name) != 0
&& strcasecmp("User-Agent",header_name) != 0);
}
belle_sip_request_t* belle_sip_request_create(belle_sip_uri_t *requri, const char* method,
belle_sip_header_call_id_t *callid,
belle_sip_header_cseq_t * cseq,
......@@ -512,17 +532,77 @@ belle_sip_request_t* belle_sip_request_create(belle_sip_uri_t *requri, const cha
{
belle_sip_request_t *ret=belle_sip_request_new();
belle_sip_header_max_forwards_t *mf=belle_sip_header_max_forwards_new();
belle_sip_list_t* iterator;
if (max_forward==0) max_forward=70;
belle_sip_header_max_forwards_set_max_forwards(mf,max_forward);
belle_sip_request_set_uri(ret,requri);
belle_sip_request_set_method(ret,method);
belle_sip_message_add_header((belle_sip_message_t*)ret,BELLE_SIP_HEADER(via));
belle_sip_message_add_header((belle_sip_message_t*)ret,BELLE_SIP_HEADER(from));
belle_sip_message_add_header((belle_sip_message_t*)ret,BELLE_SIP_HEADER(to));
if (to) belle_sip_message_add_header((belle_sip_message_t*)ret,BELLE_SIP_HEADER(to)); /*to might be in header uri*/
belle_sip_message_add_header((belle_sip_message_t*)ret,BELLE_SIP_HEADER(cseq));
belle_sip_message_add_header((belle_sip_message_t*)ret,BELLE_SIP_HEADER(callid));
belle_sip_message_add_header((belle_sip_message_t*)ret,BELLE_SIP_HEADER(mf));
if (!belle_sip_message_get_header_by_type(ret,belle_sip_header_max_forwards_t))
belle_sip_message_add_header((belle_sip_message_t*)ret,BELLE_SIP_HEADER(mf));
else
belle_sip_object_unref(mf);
/*
19.1.5 Forming Requests from a URI
An implementation needs to take care when forming requests directly
from a URI. URIs from business cards, web pages, and even from
sources inside the protocol such as registered contacts may contain
inappropriate header fields or body parts.
An implementation MUST include any provided transport, maddr, ttl, or
user parameter in the Request-URI of the formed request. If the URI
contains a method parameter, its value MUST be used as the method of
the request. The method parameter MUST NOT be placed in the
Request-URI. Unknown URI parameters MUST be placed in the message's
Request-URI.
An implementation SHOULD treat the presence of any headers or body
parts in the URI as a desire to include them in the message, and
choose to honor the request on a per-component basis.
An implementation SHOULD NOT honor these obviously dangerous header
fields: From, Call-ID, CSeq, Via, and Record-Route.
An implementation SHOULD NOT honor any requested Route header field
values in order to not be used as an unwitting agent in malicious
attacks.
An implementation SHOULD NOT honor requests to include header fields
that may cause it to falsely advertise its location or capabilities.
These include: Accept, Accept-Encoding, Accept-Language, Allow,
Contact (in its dialog usage), Organization, Supported, and User-
Agent.
An implementation SHOULD verify the accuracy of any requested
descriptive header fields, including: Content-Disposition, Content-
Encoding, Content-Language, Content-Length, Content-Type, Date,
Mime-Version, and Timestamp.*/
if (belle_sip_uri_get_header_names(requri)) {
for (iterator=(belle_sip_list_t*)belle_sip_uri_get_header_names(requri);iterator!=NULL;iterator=iterator->next) {
const char* header_name=(const char*)iterator->data;
/*1 check header name*/
if (is_authorized_uri_header(header_name)) {
belle_sip_header_extension_t* extended_header = belle_sip_header_extension_create(header_name, belle_sip_uri_get_header(requri, header_name));
if (extended_header) {
belle_sip_message_add_header((belle_sip_message_t*)ret,BELLE_SIP_HEADER(extended_header));
}
} else {
belle_sip_warning("Skiping uri header [%s] for request [%p]",header_name,requri);
}
}
}
belle_sip_uri_headers_clean(requri); /*remove all headers*/
belle_sip_request_set_uri(ret,requri);
return ret;
}
......
......@@ -482,6 +482,65 @@ static void testRFC2543Compat(void) {
belle_sip_object_unref(message);
}
static void testUriHeadersInInvite(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);
const char* raw_uri="sip:toto@titi.com"
"?header1=blabla"
"&header2=blue%3Bweftutu%3Dbla"
"&From=toto"
"&To=sip%3Atoto%40titi.com"
"&Call-ID=asdads"
"&CSeq=asdasd"
"&Via=asdasd"
"&Accept=adsad"
"&Accept-Encoding=adsad"
"&Accept-Language=adsad"
"&Allow=adsad"
"&Record-Route=adsad"
"&Contact=adsad"
"&Organization=adsad"
"&Supported=adsad"
"&User-Agent=adsad";
belle_sip_header_t* raw_header;
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")
,NULL
,belle_sip_header_via_new()
,70);
CU_ASSERT_PTR_NOT_NULL(request);
CU_ASSERT_PTR_NOT_NULL(raw_header=belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),"header1"));
if (raw_header) {
CU_ASSERT_STRING_EQUAL(belle_sip_header_extension_get_value(BELLE_SIP_HEADER_EXTENSION(raw_header)),"blabla");
}
CU_ASSERT_PTR_NOT_NULL(raw_header=belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),"header2"));
if (raw_header) {
CU_ASSERT_STRING_EQUAL(belle_sip_header_extension_get_value(BELLE_SIP_HEADER_EXTENSION(raw_header)),"blue;weftutu=bla");
}
CU_ASSERT_PTR_NOT_NULL(raw_header=belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),"To"));
if (raw_header) {
CU_ASSERT_STRING_EQUAL(belle_sip_header_extension_get_value(BELLE_SIP_HEADER_EXTENSION(raw_header)),"sip:toto@titi.com");
}
CU_ASSERT_STRING_NOT_EQUAL(belle_sip_header_get_unparsed_value(belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),"From")),"toto");
CU_ASSERT_PTR_NULL(belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),"Record-Route"));
CU_ASSERT_PTR_NULL(belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),"Accept"));
CU_ASSERT_PTR_NULL(belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),"Accept-Encoding"));
CU_ASSERT_PTR_NULL(belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),"Accept-Language"));
CU_ASSERT_PTR_NULL(belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),"Allow"));
CU_ASSERT_PTR_NULL(belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),"Contact"));
CU_ASSERT_PTR_NULL(belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),"Organization"));
CU_ASSERT_PTR_NULL(belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),"Supported"));
CU_ASSERT_PTR_NULL(belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),"User-Agent"));
belle_sip_object_unref(request);
}
/* NOTE - ORDER IS IMPORTANT - MUST TEST fread() AFTER fprintf() */
test_t message_tests[] = {
{ "REGISTER", testRegisterMessage },
......@@ -496,7 +555,8 @@ test_t message_tests[] = {
{ "Malformed register", testMalformedOptionnalHeaderInMessage },
{ "Channel parser error recovery", channel_parser_tester_recovery_from_error},
{ "Channel parser malformed start", channel_parser_malformed_start},
{ "RFC2543 compatibility", testRFC2543Compat}
{ "RFC2543 compatibility", testRFC2543Compat},
{ "Uri headers in sip INVITE",testUriHeadersInInvite}
};
test_suite_t message_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