1 /*
2 belle-sip - SIP (RFC3261) library.
3 Copyright (C) 2010 Belledonne Communications SARL
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "belle-sip/sip-uri.h"
20 #include "belle-sip/parameters.h"
21 #include <stdlib.h>
22 #include <string.h>
23 #include <stdarg.h>
24 #include "grammars/belle_sip_messageParser.h"
25 #include "grammars/belle_sip_messageLexer.h"
26 #include "belle_sip_internal.h"
27 #include "listeningpoint_internal.h"
28
29
30 #define SIP_URI_GET_SET_STRING(attribute) GET_SET_STRING(belle_sip_uri,attribute)
31 #define SIP_URI_GET_SET_STRING_PARAM(attribute) GET_SET_STRING_PARAM2(belle_sip_uri,attribute,attribute##_param)
32
33
34 #define SIP_URI_GET_SET_UINT(attribute) GET_SET_INT(belle_sip_uri,attribute,unsigned int)
35 #define SIP_URI_GET_SET_INT(attribute) GET_SET_INT(belle_sip_uri,attribute,int)
36 #define SIP_URI_GET_SET_INT_PARAM(attribute) GET_SET_INT_PARAM2(belle_sip_uri,attribute,int,attribute##_param)
37
38
39 #define SIP_URI_GET_SET_BOOL(attribute) GET_SET_BOOL(belle_sip_uri,attribute,is)
40 #define SIP_URI_HAS_SET_BOOL(attribute) GET_SET_BOOL(belle_sip_uri,attribute,has)
41 #define SIP_URI_HAS_SET_BOOL_PARAM(attribute) GET_SET_BOOL_PARAM2(belle_sip_uri,attribute,has,attribute##_param)
42
43
44
45 struct _belle_sip_uri {
46 belle_sip_parameters_t params;
47 unsigned int secure;
48 char* user;
49 char* user_password;
50 char* host;
51 int port;
52 belle_sip_parameters_t * header_list;
53 };
54
belle_sip_uri_destroy(belle_sip_uri_t * uri)55 static void belle_sip_uri_destroy(belle_sip_uri_t* uri) {
56 if (uri->user) belle_sip_free (uri->user);
57 if (uri->host) belle_sip_free (uri->host);
58 if (uri->user_password) belle_sip_free (uri->user_password);
59 belle_sip_object_unref(BELLE_SIP_OBJECT(uri->header_list));
60 }
61
belle_sip_uri_clone(belle_sip_uri_t * uri,const belle_sip_uri_t * orig)62 static void belle_sip_uri_clone(belle_sip_uri_t* uri, const belle_sip_uri_t *orig){
63 uri->secure=orig->secure;
64 uri->user=orig->user?belle_sip_strdup(orig->user):NULL;
65 uri->user_password=orig->user_password?belle_sip_strdup(orig->user_password):NULL;
66 uri->host=orig->host?belle_sip_strdup(orig->host):NULL;
67 uri->port=orig->port;
68 if (orig->header_list){
69 uri->header_list=(belle_sip_parameters_t*)belle_sip_object_clone(BELLE_SIP_OBJECT(orig->header_list));
70 belle_sip_object_ref(uri->header_list);
71 }
72
73 }
74
encode_params(belle_sip_param_pair_t * container,belle_sip_list_t ** newlist)75 static void encode_params(belle_sip_param_pair_t* container, belle_sip_list_t** newlist) {
76 char *escapedName = belle_sip_uri_to_escaped_parameter(container->name);
77 char *escapedValue = container->value? belle_sip_uri_to_escaped_parameter(container->value) : NULL;
78 *newlist = belle_sip_list_append(*newlist, belle_sip_param_pair_new(escapedName, escapedValue));
79 if (escapedName) free(escapedName);
80 if (escapedValue) free(escapedValue);
81 }
82
encode_headers(belle_sip_param_pair_t * container,belle_sip_list_t ** newlist)83 static void encode_headers(belle_sip_param_pair_t* container, belle_sip_list_t** newlist) {
84 char *escapedName = belle_sip_uri_to_escaped_header(container->name);
85 char *escapedValue = container->value? belle_sip_uri_to_escaped_header(container->value) : NULL;
86 *newlist = belle_sip_list_append(*newlist, belle_sip_param_pair_new(escapedName, escapedValue));
87 if (escapedName) free(escapedName);
88 if (escapedValue) free(escapedValue);
89 }
90
belle_sip_uri_marshal(const belle_sip_uri_t * uri,char * buff,size_t buff_size,size_t * offset)91 belle_sip_error_code belle_sip_uri_marshal(const belle_sip_uri_t* uri, char* buff, size_t buff_size, size_t *offset) {
92 const belle_sip_list_t* list;
93 belle_sip_error_code error=BELLE_SIP_OK;
94
95 error=belle_sip_snprintf(buff,buff_size,offset,"%s:",uri->secure?"sips":"sip");
96 if (error!=BELLE_SIP_OK) return error;
97
98 if (uri->user && uri->user[0]!='\0') {
99 char* escaped_username=belle_sip_uri_to_escaped_username(uri->user);
100 error=belle_sip_snprintf(buff,buff_size,offset,"%s",escaped_username);
101 belle_sip_free(escaped_username);
102 if (error!=BELLE_SIP_OK) return error;
103
104 if (uri->user_password) {
105 char* escaped_password=belle_sip_uri_to_escaped_userpasswd(uri->user_password);
106 error=belle_sip_snprintf(buff,buff_size,offset,":%s",escaped_password);
107 belle_sip_free(escaped_password);
108 if (error!=BELLE_SIP_OK) return error;
109 }
110 error=belle_sip_snprintf(buff,buff_size,offset,"@");
111 if (error!=BELLE_SIP_OK) return error;
112
113 }
114
115 if (uri->host) {
116 if (strchr(uri->host,':')) { /*ipv6*/
117 error=belle_sip_snprintf(buff,buff_size,offset,"[%s]",uri->host);
118 } else {
119 error=belle_sip_snprintf(buff,buff_size,offset,"%s",uri->host);
120 }
121 if (error!=BELLE_SIP_OK) return error;
122 } else {
123 belle_sip_warning("no host found in this uri");
124 }
125
126 if (uri->port!=0) {
127 error=belle_sip_snprintf(buff,buff_size,offset,":%i",uri->port);
128 if (error!=BELLE_SIP_OK) return error;
129 }
130
131 {
132 belle_sip_parameters_t *encparams = belle_sip_parameters_new();
133 belle_sip_list_for_each2(uri->params.param_list, (void (*)(void *, void *))encode_params, &encparams->param_list);
134 error=belle_sip_parameters_marshal(encparams,buff,buff_size,offset);
135 belle_sip_object_unref(encparams);
136 if (error!=BELLE_SIP_OK) return error;
137 }
138
139 {
140 belle_sip_list_t * encheaders = NULL;
141 belle_sip_list_for_each2(uri->header_list->param_list, (void (*)(void *, void *))encode_headers, &encheaders);
142
143 for(list=encheaders;list!=NULL;list=list->next){
144 belle_sip_param_pair_t* container = list->data;
145 if (list == encheaders) {
146 //first case
147 error=belle_sip_snprintf(buff,buff_size,offset,"?%s=%s",container->name,container->value?container->value:"");
148 } else {
149 //subsequent headers
150 error=belle_sip_snprintf(buff,buff_size,offset,"&%s=%s",container->name,container->value?container->value:"");
151 }
152 if (error!=BELLE_SIP_OK) break;
153 }
154 belle_sip_list_free_with_data(encheaders,(void (*)(void*))belle_sip_param_pair_destroy);
155 }
156
157 return error;
158 }
159
160 BELLE_SIP_PARSE(uri);
161
162 BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_uri_t);
163 BELLE_SIP_INSTANCIATE_VPTR(belle_sip_uri_t,belle_sip_parameters_t,belle_sip_uri_destroy,belle_sip_uri_clone,belle_sip_uri_marshal,TRUE);
164
165
belle_sip_uri_new()166 belle_sip_uri_t* belle_sip_uri_new () {
167 belle_sip_uri_t* l_object = belle_sip_object_new(belle_sip_uri_t);
168 belle_sip_parameters_init((belle_sip_parameters_t*)l_object); /*super*/
169 l_object->header_list = belle_sip_parameters_new();
170 belle_sip_object_ref(l_object->header_list);
171 return l_object;
172 }
173
belle_sip_uri_create(const char * username,const char * host)174 belle_sip_uri_t* belle_sip_uri_create (const char* username,const char* host) {
175 belle_sip_uri_t* uri = belle_sip_uri_new();
176 belle_sip_uri_set_user(uri,username);
177 belle_sip_uri_set_host(uri,host);
178 return uri;
179 }
180
181
belle_sip_uri_to_string(const belle_sip_uri_t * uri)182 char* belle_sip_uri_to_string(const belle_sip_uri_t* uri) {
183 return belle_sip_object_to_string(BELLE_SIP_OBJECT(uri));
184 }
185
186
belle_sip_uri_get_header(const belle_sip_uri_t * uri,const char * name)187 const char* belle_sip_uri_get_header(const belle_sip_uri_t* uri,const char* name) {
188 return belle_sip_parameters_get_parameter(uri->header_list,name);
189 }
190
belle_sip_uri_set_header(belle_sip_uri_t * uri,const char * name,const char * value)191 void belle_sip_uri_set_header(belle_sip_uri_t* uri,const char* name,const char* value) {
192 belle_sip_parameters_set_parameter(uri->header_list,name,value);
193 }
194
belle_sip_uri_remove_header(belle_sip_uri_t * uri,const char * name)195 void belle_sip_uri_remove_header(belle_sip_uri_t *uri, const char *name){
196 belle_sip_parameters_remove_parameter(uri->header_list,name);
197 }
198
belle_sip_uri_get_header_names(const belle_sip_uri_t * uri)199 const belle_sip_list_t* belle_sip_uri_get_header_names(const belle_sip_uri_t* uri) {
200 return belle_sip_parameters_get_parameter_names(uri->header_list);
201 }
202
belle_sip_uri_get_listening_port(const belle_sip_uri_t * uri)203 int belle_sip_uri_get_listening_port(const belle_sip_uri_t *uri){
204 int port=belle_sip_uri_get_port(uri);
205 const char *transport=belle_sip_uri_get_transport_param(uri);
206 if (!transport) {
207 transport=belle_sip_uri_is_secure(uri)?"tls":"udp";
208 }
209 if (port==0)
210 port=belle_sip_listening_point_get_well_known_port(transport);
211 return port;
212 }
213
belle_sip_uri_fix(belle_sip_uri_t * uri)214 void belle_sip_uri_fix(belle_sip_uri_t *uri){
215 /*nop, to be removed*/
216 }
217
218 SIP_URI_GET_SET_BOOL(secure)
219
SIP_URI_GET_SET_STRING(user)220 SIP_URI_GET_SET_STRING(user)
221 SIP_URI_GET_SET_STRING(user_password)
222 SIP_URI_GET_SET_STRING(host)
223 SIP_URI_GET_SET_INT(port)
224
225 SIP_URI_GET_SET_STRING_PARAM(transport)
226 SIP_URI_GET_SET_STRING_PARAM(user)
227 SIP_URI_GET_SET_STRING_PARAM(method)
228 SIP_URI_GET_SET_STRING_PARAM(maddr)
229 SIP_URI_GET_SET_INT_PARAM(ttl)
230 SIP_URI_HAS_SET_BOOL_PARAM(lr)
231
232
233 const belle_sip_parameters_t* belle_sip_uri_get_headers(const belle_sip_uri_t* uri) {
234 return uri->header_list;
235 }
236
237
belle_sip_uri_headers_clean(belle_sip_uri_t * uri)238 void belle_sip_uri_headers_clean(belle_sip_uri_t* uri) {
239 belle_sip_parameters_clean(uri->header_list);
240 }
241
242
uri_strcmp(const char * a,const char * b,int case_sensitive)243 static int uri_strcmp(const char*a,const char*b,int case_sensitive) {
244 int result = 0;
245 size_t index_a=0,index_b=0;
246 char char_a,char_b;
247
248 if (a == NULL && b == NULL) {
249 goto end;
250 }
251 if ((a != NULL && b == NULL) || (a == NULL && b != NULL)){
252 result = 1;
253 goto end;
254 }
255
256 do {
257 index_a+=belle_sip_get_char(a+index_a,&char_a);
258 index_b+=belle_sip_get_char(b+index_b,&char_b);
259 if (!case_sensitive && char_a<0x7B && char_a>0x60) char_a-=0x20;
260 if (!case_sensitive && char_b<0x7B && char_b>0x60) char_b-=0x20;
261 result=(char_a!=char_b);
262 if (result) break;
263 if (char_a == '\0' || char_b == '\0') break;
264 }while(1);
265 end:
266 return result;
267 }
268
269 #define IS_EQUAL(a,b) (uri_strcmp(a,b,TRUE)==0)
270
271 #define IS_EQUAL_CASE(a,b) (uri_strcmp(a,b,FALSE)==0)
272 #define PARAM_CASE_CMP(uri_a,uri_b,param) \
273 a_param=belle_sip_parameters_get_case_parameter((belle_sip_parameters_t*) uri_a,param); \
274 b_param=belle_sip_parameters_get_case_parameter((belle_sip_parameters_t*) uri_b,param);\
275 if (!IS_EQUAL_CASE(a_param,b_param)) return 0;
276
277 /*
278 * RFC 3261 SIP: Session Initiation Protocol June 2002
279 * 19.1.4 URI Comparison
280
281 Some operations in this specification require determining whether two
282 SIP or SIPS URIs are equivalent. In this specification, registrars
283 need to compare bindings in Contact URIs in REGISTER requests (see
284 Section 10.3.). SIP and SIPS URIs are compared for equality
285 according to the following rules:
286 */
belle_sip_uri_equals(const belle_sip_uri_t * uri_a,const belle_sip_uri_t * uri_b)287 int belle_sip_uri_equals(const belle_sip_uri_t* uri_a,const belle_sip_uri_t* uri_b) {
288 const belle_sip_list_t * params;
289 const char* b_param;
290 const char* a_param;
291 /*
292 o A SIP and SIPS URI are never equivalent.
293 */
294 if (belle_sip_uri_is_secure(uri_a)!=belle_sip_uri_is_secure(uri_b)) {
295 return 0;
296 }
297 /*
298 o Comparison of the userinfo of SIP and SIPS URIs is case-
299 sensitive. This includes userinfo containing passwords or
300 formatted as telephone-subscribers. Comparison of all other
301 components of the URI is case-insensitive unless explicitly
302 defined otherwise.
303 */
304 if (!IS_EQUAL(uri_a->user,uri_b->user)) return 0;
305
306 /*
307 o The ordering of parameters and header fields is not significant
308 in comparing SIP and SIPS URIs.
309
310 o Characters other than those in the "reserved" set (see RFC 2396
311 [5]) are equivalent to their ""%" HEX HEX" encoding.
312
313 o An IP address that is the result of a DNS lookup of a host name
314 does not match that host name.
315
316 o For two URIs to be equal, the user, password, host, and port
317 components must match.
318 */
319 if (!IS_EQUAL_CASE(uri_a->host,uri_b->host)) {
320 return 0;
321 }
322 if (uri_a->port != uri_b->port) return 0;
323 /*
324 A URI omitting the user component will not match a URI that
325 includes one. A URI omitting the password component will not
326 match a URI that includes one.
327
328 A URI omitting any component with a default value will not
329 match a URI explicitly containing that component with its
330 default value. For instance, a URI omitting the optional port
331 component will not match a URI explicitly declaring port 5060.
332 The same is true for the transport-parameter, ttl-parameter,
333 user-parameter, and method components.
334
335 Defining sip:user@host to not be equivalent to
336 sip:user@host:5060 is a change from RFC 2543. When deriving
337 addresses from URIs, equivalent addresses are expected from
338 equivalent URIs. The URI sip:user@host:5060 will always
339 resolve to port 5060. The URI sip:user@host may resolve to
340 other ports through the DNS SRV mechanisms detailed in [4].
341
342 o URI uri-parameter components are compared as follows:
343
344 - Any uri-parameter appearing in both URIs must match.
345 */
346 /*
347 * - A user, ttl, or method uri-parameter appearing in only one
348 URI never matches, even if it contains the default value.
349 - A URI that includes an maddr parameter will not match a URI
350 that contains no maddr parameter.
351 * */
352 PARAM_CASE_CMP(uri_a,uri_b,"transport")
353 PARAM_CASE_CMP(uri_a,uri_b,"user")
354 PARAM_CASE_CMP(uri_a,uri_b,"ttl")
355 PARAM_CASE_CMP(uri_a,uri_b,"method")
356 PARAM_CASE_CMP(uri_a,uri_b,"maddr")
357
358
359 for(params=belle_sip_parameters_get_parameters((belle_sip_parameters_t*) uri_a);params!=NULL;params=params->next) {
360 if ((b_param=belle_sip_parameters_get_parameter((belle_sip_parameters_t*) uri_b,(const char*)params->data)) != NULL) {
361 if (!IS_EQUAL_CASE(b_param,(const char*)params->data)) return 0;
362 }
363 }
364
365 /*
366
367
368 - All other uri-parameters appearing in only one URI are
369 ignored when comparing the URIs.
370 */
371 /* *fixme ignored for now*/
372 /*
373 o URI header components are never ignored. Any present header
374 component MUST be present in both URIs and match for the URIs
375 to match. The matching rules are defined for each header field
376 in Section 20.
377 */
378 return 1;
379 }
380
381 /*uri checker*/
382
383
384 /*
385 * From 19.1.1 SIP and SIPS URI Components
386 * dialog
387 reg./redir. Contact/
388 default Req.-URI To From Contact R-R/Route external
389 user -- o o o o o o
390 password -- o o o o o o
391 host -- m m m m m m
392 port (1) o - - o o o
393 user-param ip o o o o o o
394 method INVITE - - - - - o
395 maddr-param -- o - - o o o
396 ttl-param 1 o - - o - o
397 transp.-param (2) o - - o o o
398 lr-param -- o - - - o o
399 other-param -- o o o o o o
400 headers -- - - - o - o
401
402 (1): The default port value is transport and scheme dependent. The
403 default is 5060 for sip: using UDP, TCP, or SCTP. The default is
404 5061 for sip: using TLS over TCP and sips: over TCP.
405
406 (2): The default transport is scheme dependent. For sip:, it is UDP.
407 For sips:, it is TCP.
408
409 Table 1: Use and default values of URI components for SIP header
410 field values, Request-URI and references*/
411
412
413 typedef enum {
414 m /*mandotory*/
415 , o /*optionnal*/
416 , na /*not allowd*/
417 } mark;
418
mark_to_string(mark value)419 static const char* mark_to_string(mark value) {
420 switch (value) {
421 case o: return "optionnal";
422 case m: return "mandatory";
423 case na: return "not allowed";
424 }
425 return "unknown";
426 }
427
428 typedef struct uri_components {
429 const char * name;
430 mark user;
431 mark password;
432 mark host;
433 mark port;
434 mark user_param;
435 mark method;
436 mark maddr_param;
437 mark ttl_param;
438 mark transp_param;
439 mark lr_param;
440 mark other_param;
441 mark headers;
442 } uri_components_t;
443
444
445 /*belle sip allows contact header without host because stack will auutomatically put host if missing*/
446 static uri_components_t uri_component_use_for_request = {"Req.-URI" ,o ,o ,m ,o ,o ,na ,o ,o ,o ,o ,o ,na};
447 static uri_components_t uri_component_use_for_header_to = {"Header To" ,o ,o ,m ,na ,o ,na ,na ,na ,na ,na ,o ,na};
448 static uri_components_t uri_component_use_for_header_from = {"Header From" ,o ,o ,m ,na ,o ,na ,na ,na ,na ,na ,o ,na};
449 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};
450 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};
451 static uri_components_t uri_component_use_for_external = {"External" ,o ,o ,m ,o ,o ,o ,o ,o ,o ,o ,o ,o};
452
453
check_component(int is_present,mark requirement)454 static int check_component(int is_present,mark requirement) {
455 switch (requirement) {
456 case o: return TRUE;
457 case m: return is_present;
458 case na: return !is_present;
459 }
460 return 0;
461 }
462
463 #define CHECK_URI_COMPONENT(uri_component,uri_component_name,component_use_rule,component_use_rule_name) \
464 if (!check_component(uri_component,component_use_rule)) {\
465 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);\
466 return FALSE;\
467 }
468
check_uri_components(const belle_sip_uri_t * uri,const uri_components_t * components_use)469 static int check_uri_components(const belle_sip_uri_t* uri, const uri_components_t* components_use) {
470
471 CHECK_URI_COMPONENT(uri->user!=NULL,"user",components_use->user,components_use->name)
472 CHECK_URI_COMPONENT(uri->host!=NULL,"host",components_use->host,components_use->name)
473 CHECK_URI_COMPONENT(uri->port>0,"port",components_use->port,components_use->name)
474 CHECK_URI_COMPONENT(belle_sip_parameters_has_parameter(&uri->params,"maddr"),"maddr-param",components_use->maddr_param,components_use->name)
475 CHECK_URI_COMPONENT(belle_sip_parameters_has_parameter(&uri->params,"ttl"),"ttl-param",components_use->ttl_param,components_use->name)
476 CHECK_URI_COMPONENT(belle_sip_parameters_has_parameter(&uri->params,"transport"),"transp.-param",components_use->transp_param,components_use->name)
477 CHECK_URI_COMPONENT(belle_sip_parameters_has_parameter(&uri->params,"lr"),"lr-param",components_use->lr_param,components_use->name)
478 /*..*/
479 CHECK_URI_COMPONENT(belle_sip_list_size(belle_sip_parameters_get_parameters(uri->header_list))>0,"headers",components_use->headers,components_use->name)
480 return TRUE;
481 }
482
483 /*return 0 if not compliant*/
belle_sip_uri_check_components_from_request_uri(const belle_sip_uri_t * uri)484 int belle_sip_uri_check_components_from_request_uri(const belle_sip_uri_t* uri) {
485 return check_uri_components(uri,&uri_component_use_for_request);
486 }
belle_sip_uri_check_components_from_context(const belle_sip_uri_t * uri,const char * method,const char * header_name)487 int belle_sip_uri_check_components_from_context(const belle_sip_uri_t* uri,const char* method,const char* header_name) {
488
489 if (strcasecmp(BELLE_SIP_FROM,header_name)==0)
490 return check_uri_components(uri,&uri_component_use_for_header_from);
491 else if (strcasecmp(BELLE_SIP_TO,header_name)==0)
492 return check_uri_components(uri,&uri_component_use_for_header_to);
493 else if (strcasecmp(BELLE_SIP_CONTACT,header_name)==0 && method && strcasecmp("REGISTER",method)==0)
494 return check_uri_components(uri,&uri_component_use_for_contact_in_reg);
495 else if (strcasecmp(BELLE_SIP_CONTACT,header_name)==0
496 || strcasecmp(BELLE_SIP_RECORD_ROUTE,header_name)==0
497 || strcasecmp(BELLE_SIP_ROUTE,header_name)==0)
498 return check_uri_components(uri,&uri_component_use_for_dialog_ct_rr_ro);
499 else
500 return check_uri_components(uri,&uri_component_use_for_external);
501
502
503 }
504 /*fast uri implemenation*/
505 typedef belle_sip_uri_t belle_sip_fast_uri_t;
506 BELLE_SIP_PARSE(fast_uri);
507