1 /*
2 Copyright (C) 2002-2008 Thomas Ries <tries@gmx.net>
3
4 This file is part of Siproxd.
5
6 Siproxd is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 Siproxd is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Siproxd; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20 #include "config.h"
21
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <errno.h>
25 #include <time.h>
26 #include <signal.h>
27 #include <string.h>
28 #include <sys/socket.h>
29 #include <netinet/in.h>
30 #include <arpa/inet.h>
31 #include <netdb.h>
32 #include <net/if.h>
33 #include <sys/ioctl.h>
34
35 #include <sys/types.h>
36 #include <pwd.h>
37
38 #include <osipparser2/osip_parser.h>
39 #include <osipparser2/osip_md5.h>
40
41 #include "siproxd.h"
42 #include "digcalc.h"
43 #include "log.h"
44
45 static char const ident[]="$Id: sip_utils.c 538 2016-02-24 19:14:23Z hb9xar $";
46
47
48 /* configuration storage */
49 extern struct siproxd_config configuration;
50
51 extern int h_errno;
52
53 extern struct urlmap_s urlmap[]; /* URL mapping table */
54
55
56 /*
57 * create a reply template from an given SIP request
58 *
59 * RETURNS a pointer to osip_message_t
60 */
msg_make_template_reply(sip_ticket_t * ticket,int code)61 osip_message_t *msg_make_template_reply (sip_ticket_t *ticket, int code) {
62 osip_message_t *request=ticket->sipmsg;
63 osip_message_t *response;
64 int pos;
65
66 if (request->to==NULL) {
67 ERROR("msg_make_template_reply: empty To in request header");
68 return NULL;
69 }
70
71 if (request->from==NULL) {
72 ERROR("msg_make_template_reply: empty From in request header");
73 return NULL;
74 }
75
76 osip_message_init (&response);
77 if (response == NULL) {
78 ERROR("msg_make_template_reply: osip_message_init() failed");
79 return NULL;
80 }
81 response->message=NULL;
82 osip_message_set_version (response, osip_strdup ("SIP/2.0"));
83 osip_message_set_status_code (response, code);
84 osip_message_set_reason_phrase (response,
85 osip_strdup(osip_message_get_reason (code)));
86
87
88 osip_to_clone (request->to, &response->to);
89 osip_from_clone (request->from, &response->from);
90
91 /* if 3xx, also include 1st contact header */
92 if ((code==200) || ((code>=300) && (code<400))) {
93 osip_contact_t *req_contact = NULL;
94 osip_contact_t *res_contact = NULL;
95 osip_message_get_contact(request, 0, &req_contact);
96 if (req_contact) osip_contact_clone (req_contact, &res_contact);
97 if (res_contact) osip_list_add(&(response->contacts),res_contact,0);
98 }
99
100 /* via headers */
101 pos = 0;
102 while (!osip_list_eol (&(request->vias), pos)) {
103 char *tmp;
104 osip_via_t *via;
105 via = (osip_via_t *) osip_list_get (&(request->vias), pos);
106 osip_via_to_str (via, &tmp);
107
108 osip_message_set_via (response, tmp);
109 osip_free (tmp);
110 pos++;
111 }
112
113 osip_call_id_clone(request->call_id,&response->call_id);
114
115 osip_cseq_clone(request->cseq,&response->cseq);
116
117 return response;
118 }
119
120
121 /*
122 * check for a via loop.
123 * It checks for the presense of a via entry that holds one of
124 * my IP addresses and is *not* the topmost via.
125 *
126 * RETURNS
127 * STS_TRUE if loop detected
128 * STS_FALSE if no loop
129 */
check_vialoop(sip_ticket_t * ticket)130 int check_vialoop (sip_ticket_t *ticket) {
131 /*
132 !!! actually this is a problematic one.
133 1) for requests, I must search the whole VIA list
134 (topmost via is the previos station in the path)
135
136 2) for responses I must skip the topmost via, as this is mine
137 (and will be removed later on)
138
139 3) What happens if we have 'clashes' with private addresses??
140 From that point of view, siproxd *should* not try to
141 check against it's local IF addresses if they are private.
142 this then of course again can lead to a endless loop...
143
144 -> Might use a fixed unique part of branch parameter to identify
145 that it is MY via
146
147 */
148 osip_message_t *my_msg=ticket->sipmsg;
149 int sts;
150 int pos;
151 int found_own_via;
152
153 found_own_via=0;
154 pos = 1; /* for detecting a loop, don't check the first entry
155 as this is my own VIA! */
156 while (!osip_list_eol (&(my_msg->vias), pos)) {
157 osip_via_t *via;
158 via = (osip_via_t *) osip_list_get (&(my_msg->vias), pos);
159 sts = is_via_local (via);
160 if (sts == STS_TRUE) found_own_via+=1;
161 pos++;
162 }
163
164 /*
165 * what happens if a message is coming back to me legally?
166 * UA1 -->--\ /-->--\
167 * siproxd Registrar
168 * UA2 --<--/ \--<--/
169 *
170 * This may also lead to a VIA loop - so I probably must take the branch
171 * parameter into count (or a unique part of it) OR just allow at least 2
172 * vias of my own.
173 */
174 return (found_own_via>2)? STS_TRUE : STS_FALSE;
175 }
176
177
178 /*
179 * check if a given osip_via_t is local. I.e. its address is owned
180 * by my inbound or outbound interface (or externally defined using
181 * the host_outbound directive
182 *
183 * RETURNS
184 * STS_TRUE if the given VIA is one of my interfaces
185 * STS_FALSE otherwise
186 */
is_via_local(osip_via_t * via)187 int is_via_local (osip_via_t *via) {
188 int sts, found;
189 struct in_addr addr_via, addr_myself;
190 int port;
191 int i;
192
193 if (via==NULL) {
194 ERROR("called is_via_local with NULL via");
195 return STS_FALSE;
196 }
197
198 DEBUGC(DBCLASS_BABBLE,"via name %s",via->host);
199 if (utils_inet_aton(via->host,&addr_via) == 0) {
200 /* need name resolution */
201 sts=get_ip_by_host(via->host, &addr_via);
202 if (sts == STS_FAILURE) {
203 DEBUGC(DBCLASS_DNS, "is_via_local: cannot resolve VIA [%s]",
204 via->host);
205 return STS_FAILURE;
206 }
207 }
208
209 if (via->port) {
210 port=atoi(via->port);
211 if ((port<=0) || (port>65535)) port=SIP_PORT;
212 } else {
213 port=SIP_PORT;
214 }
215
216 found=0;
217 for (i=0; i<3; i++) {
218 if (i < 2) {
219 /* search my in/outbound interfaces */
220 DEBUGC(DBCLASS_BABBLE,"resolving IP of interface %s",
221 (i==IF_INBOUND)? "inbound":"outbound");
222 if (get_interface_ip(i, &addr_myself) != STS_SUCCESS) {
223 continue;
224 }
225 } else {
226 /* check against a possible defined 'host_outbound' */
227 /* defined? */
228 if (configuration.outbound_host == NULL) continue;
229 DEBUGC(DBCLASS_BABBLE,"resolving IP of interface 'host_outbound'");
230 /* lookup */
231 if (get_ip_by_host(configuration.outbound_host,
232 &addr_myself) != STS_SUCCESS) continue;
233 }
234
235 /* check the extracted VIA against my own host addresses */
236 if ( (memcmp(&addr_myself, &addr_via, sizeof(addr_myself))==0) &&
237 (port == configuration.sip_listen_port) ) {
238 DEBUG("got address match [%s]", utils_inet_ntoa(addr_via));
239 found=1;
240 break;
241 }
242 }
243
244 return (found)? STS_TRUE : STS_FALSE;
245 }
246
247
248 /*
249 * compares two URLs
250 * (by now, only scheme, hostname and username are compared)
251 *
252 * RETURNS
253 * STS_SUCCESS if equal
254 * STS_FAILURE if non equal or error
255 */
compare_url(osip_uri_t * url1,osip_uri_t * url2)256 int compare_url(osip_uri_t *url1, osip_uri_t *url2) {
257 int sts1, sts2;
258 struct in_addr addr1, addr2;
259
260 /* sanity checks */
261 if ((url1 == NULL) || (url2 == NULL)) {
262 ERROR("compare_url: NULL ptr: url1=0x%p, url2=0x%p",url1, url2);
263 return STS_FAILURE;
264 }
265
266 /* sanity checks: host part is a MUST */
267 if ((url1->host == NULL) || (url2->host == NULL)) {
268 ERROR("compare_url: NULL ptr: url1->host=0x%p, url2->host=0x%p",
269 url1->host, url2->host);
270 return STS_FAILURE;
271 }
272
273 #if 0
274 DEBUGC(DBCLASS_BABBLE, "comparing urls: %s:%s@%s -> %s:%s@%s",
275 (url1->scheme) ? url1->scheme : "(null)",
276 (url1->username) ? url1->username : "(null)",
277 (url1->host) ? url1->host : "(null)",
278 (url2->scheme) ? url2->scheme : "(null)",
279 (url2->username) ? url2->username : "(null)",
280 (url2->host) ? url2->host : "(null)");
281 #endif
282
283 /* compare SCHEME (if present) case INsensitive */
284 if (url1->scheme && url2->scheme) {
285 if (osip_strcasecmp(url1->scheme, url2->scheme) != 0) {
286 DEBUGC(DBCLASS_BABBLE, "compare_url: scheme mismatch");
287 return STS_FAILURE;
288 }
289 } else {
290 WARN("compare_url: NULL scheme - ignoring");
291 }
292
293 /* compare username (if present) case sensitive */
294 if (url1->username && url2->username) {
295 if (strcmp(url1->username, url2->username) != 0) {
296 // DEBUGC(DBCLASS_BABBLE, "compare_url: username mismatch");
297 return STS_FAILURE;
298 }
299 } else {
300 // DEBUGC(DBCLASS_BABBLE, "compare_url: NULL username - ignoring");
301 }
302
303
304 /*
305 * now, try to resolve the host. If resolveable, compare
306 * IP addresses - if not resolveable, compare the host names
307 * itselfes
308 */
309
310 /* get the IP addresses from the (possible) hostnames */
311 sts1=get_ip_by_host(url1->host, &addr1);
312 if (sts1 == STS_FAILURE) {
313 DEBUGC(DBCLASS_BABBLE, "compare_url: cannot resolve host [%s]",
314 url1->host);
315 }
316
317 sts2=get_ip_by_host(url2->host, &addr2);
318 if (sts2 == STS_FAILURE) {
319 DEBUGC(DBCLASS_BABBLE, "compare_url: cannot resolve host [%s]",
320 url2->host);
321 }
322
323 if ((sts1 == STS_SUCCESS) && (sts2 == STS_SUCCESS)) {
324 /* compare IP addresses */
325 if (memcmp(&addr1, &addr2, sizeof(addr1))!=0) {
326 DEBUGC(DBCLASS_BABBLE, "compare_url: IP mismatch");
327 return STS_FAILURE;
328 }
329 } else {
330 /* compare hostname strings case INsensitive */
331 if (osip_strcasecmp(url1->host, url2->host) != 0) {
332 DEBUGC(DBCLASS_BABBLE, "compare_url: host name mismatch");
333 return STS_FAILURE;
334 }
335 }
336
337 /* the two URLs did pass all tests successfully - MATCH */
338 return STS_SUCCESS;
339 }
340
341
342 /*
343 * compares two Call IDs
344 * (by now, only hostname and username are compared)
345 *
346 * RETURNS
347 * STS_SUCCESS if equal
348 * STS_FAILURE if non equal or error
349 */
compare_callid(osip_call_id_t * cid1,osip_call_id_t * cid2)350 int compare_callid(osip_call_id_t *cid1, osip_call_id_t *cid2) {
351
352 if ((cid1==0) || (cid2==0)) {
353 ERROR("compare_callid: NULL ptr: cid1=0x%p, cid2=0x%p",cid1, cid2);
354 return STS_FAILURE;
355 }
356
357 /*
358 * Check number part: if present must be equal,
359 * if not present, must be not present in both cids
360 */
361 if (cid1->number && cid2->number) {
362 /* have both numbers */
363 if (strcmp(cid1->number, cid2->number) != 0) goto mismatch;
364 } else {
365 /* at least one number missing, make sure that both are empty */
366 if ( (cid1->number && (cid1->number[0]!='\0')) ||
367 (cid2->number && (cid2->number[0]!='\0'))) {
368 goto mismatch;
369 }
370 }
371
372 /*
373 * Check host part: if present must be equal,
374 * if not present, must be not present in both cids
375 */
376 if (cid1->host && cid2->host) {
377 /* have both hosts */
378 if (strcasecmp(cid1->host, cid2->host) != 0) goto mismatch;
379 } else {
380 /* at least one host missing, make sure that both are empty */
381 if ( (cid1->host && (cid1->host[0]!='\0')) ||
382 (cid2->host && (cid2->host[0]!='\0'))) {
383 goto mismatch;
384 }
385 }
386
387 DEBUGC(DBCLASS_BABBLE, "comparing callid - matched: "
388 "%s@%s <-> %s@%s",
389 cid1->number, cid1->host, cid2->number, cid2->host);
390 return STS_SUCCESS;
391
392 mismatch:
393 DEBUGC(DBCLASS_BABBLE, "comparing callid - mismatch: "
394 "%s@%s <-> %s@%s",
395 cid1->number, cid1->host, cid2->number, cid2->host);
396 return STS_FAILURE;
397 }
398
399
400 /*
401 * check if a given request is addressed to local. I.e. it is addressed
402 * to the proxy itself (IP of my inbound or outbound interface, same port)
403 *
404 * RETURNS
405 * STS_TRUE if the request is addressed local
406 * STS_FALSE otherwise
407 */
is_sipuri_local(sip_ticket_t * ticket)408 int is_sipuri_local (sip_ticket_t *ticket) {
409 osip_message_t *sip=ticket->sipmsg;
410 int found;
411 struct in_addr addr_uri, addr_myself;
412 int port;
413 int i, sts;
414
415 if (sip==NULL) {
416 ERROR("called is_sipuri_local with NULL sip");
417 return STS_FALSE;
418 }
419
420 if (!sip || !sip->req_uri) {
421 ERROR("is_sipuri_local: no request URI present");
422 return STS_FALSE;
423 }
424
425 DEBUGC(DBCLASS_DNS,"check for local SIP URI %s:%s",
426 sip->req_uri->host? sip->req_uri->host : "*NULL*",
427 sip->req_uri->port? sip->req_uri->port : "*NULL*");
428
429 if (utils_inet_aton(sip->req_uri->host, &addr_uri) == 0) {
430 /* need name resolution */
431 sts=get_ip_by_host(sip->req_uri->host, &addr_uri);
432 if (sts == STS_FAILURE) {
433 DEBUGC(DBCLASS_PROXY, "sip_gen_response: cannot resolve request uri [%s]",
434 sip->req_uri->host);
435 return STS_FALSE;
436 }
437 }
438
439 found=0;
440 for (i=0; i<2; i++) {
441 /*
442 * search my in/outbound interfaces
443 */
444 DEBUGC(DBCLASS_BABBLE,"resolving IP of interface %s",
445 (i==IF_INBOUND)? "inbound":"outbound");
446 if (get_interface_ip(i, &addr_myself) != STS_SUCCESS) {
447 continue;
448 }
449
450 /* check the extracted HOST against my own host addresses */
451 if (sip->req_uri->port) {
452 port=atoi(sip->req_uri->port);
453 if ((port<=0) || (port>65535)) port=SIP_PORT;
454 } else {
455 port=SIP_PORT;
456 }
457
458 if ( (memcmp(&addr_myself, &addr_uri, sizeof(addr_myself))==0) &&
459 (port == configuration.sip_listen_port) ) {
460 DEBUG("address match [%s]", utils_inet_ntoa(addr_uri));
461 found=1;
462 break;
463 }
464 }
465
466 DEBUGC(DBCLASS_DNS, "SIP URI is %slocal", found? "":"not ");
467 return (found)? STS_TRUE : STS_FALSE;
468 }
469
470
471 /*
472 * SIP_GEN_RESPONSE
473 *
474 * send an proxy generated response back to the client.
475 * Only errors are reported from the proxy itself.
476 * code = SIP result code to deliver
477 *
478 * RETURNS
479 * STS_SUCCESS on success
480 * STS_FAILURE on error
481 */
sip_gen_response(sip_ticket_t * ticket,int code)482 int sip_gen_response(sip_ticket_t *ticket, int code) {
483 osip_message_t *response;
484 int sts;
485 osip_via_t *via;
486 int port;
487 char *buffer;
488 size_t buflen;
489 struct in_addr addr;
490
491 /* create the response template */
492 if ((response=msg_make_template_reply(ticket, code))==NULL) {
493 ERROR("sip_gen_response: error in msg_make_template_reply");
494 return STS_FAILURE;
495 }
496
497 /* we must check if first via has x.x.x.x address. If not, we must resolve it */
498 osip_message_get_via (response, 0, &via);
499 if (via == NULL)
500 {
501 ERROR("sip_gen_response: Cannot send response - no via field");
502 osip_message_free(response);
503 return STS_FAILURE;
504 }
505
506
507 /* name resolution */
508 if (utils_inet_aton(via->host, &addr) == 0)
509 {
510 /* need name resolution */
511 DEBUGC(DBCLASS_DNS,"resolving name:%s",via->host);
512 sts = get_ip_by_host(via->host, &addr);
513 if (sts == STS_FAILURE) {
514 DEBUGC(DBCLASS_PROXY, "sip_gen_response: cannot resolve via [%s]",
515 via->host);
516 osip_message_free(response);
517 return STS_FAILURE;
518 }
519 }
520
521 sts = sip_message_to_str(response, &buffer, &buflen);
522 if (sts != 0) {
523 ERROR("sip_gen_response: msg_2char failed");
524 osip_message_free(response);
525 return STS_FAILURE;
526 }
527
528
529 if (via->port) {
530 port=atoi(via->port);
531 if ((port<=0) || (port>65535)) port=SIP_PORT;
532 } else {
533 port=SIP_PORT;
534 }
535
536 /* send to destination */
537 sipsock_send(addr, port, ticket->protocol, buffer, buflen);
538
539 /* free the resources */
540 osip_message_free(response);
541 osip_free(buffer);
542 return STS_SUCCESS;
543 }
544
545
546 /*
547 * SIP_ADD_MYVIA
548 *
549 * interface == IF_OUTBOUND, IF_INBOUND
550 *
551 * RETURNS
552 * STS_SUCCESS on success
553 * STS_FAILURE on error
554 */
sip_add_myvia(sip_ticket_t * ticket,int interface)555 int sip_add_myvia (sip_ticket_t *ticket, int interface) {
556 struct in_addr addr;
557 char tmp[URL_STRING_SIZE];
558 osip_via_t *via;
559 int sts;
560 char branch_id[VIA_BRANCH_SIZE];
561 char *myaddr;
562 int add_rport=0;
563
564 if (get_interface_ip(interface, &addr) != STS_SUCCESS) {
565 return STS_FAILURE;
566 }
567
568 /* evaluate if we need to include an ;rport */
569 /* incoming */
570 if ((configuration.use_rport & 1) &&
571 ((ticket->direction==REQTYP_INCOMING) ||
572 (ticket->direction==RESTYP_INCOMING)) ) {
573 add_rport=1;
574 } else if ((configuration.use_rport & 2) &&
575 ((ticket->direction==REQTYP_OUTGOING) ||
576 (ticket->direction==RESTYP_OUTGOING)) ) {
577 add_rport=1;
578 }
579
580 sts = sip_calculate_branch_id(ticket, branch_id);
581
582 myaddr=utils_inet_ntoa(addr);
583 if (ticket->protocol == PROTO_UDP) {
584 sprintf(tmp, "SIP/2.0/UDP %s:%i;branch=%s%s",
585 myaddr, configuration.sip_listen_port,
586 branch_id,
587 (add_rport)? ";rport":"");
588 } else {
589 sprintf(tmp, "SIP/2.0/TCP %s:%i;branch=%s%s",
590 myaddr, configuration.sip_listen_port,
591 branch_id,
592 (add_rport)? ";rport":"");
593 }
594
595 DEBUGC(DBCLASS_BABBLE,"adding VIA:%s",tmp);
596
597 sts = osip_via_init(&via);
598 if (sts!=0) return STS_FAILURE; /* allocation failed */
599
600 sts = osip_via_parse(via, tmp);
601 if (sts!=0) return STS_FAILURE;
602
603 osip_list_add(&(ticket->sipmsg->vias),via,0);
604
605 return STS_SUCCESS;
606 }
607
608
609 /*
610 * SIP_DEL_MYVIA
611 *
612 * RETURNS
613 * STS_SUCCESS on success
614 * STS_FAILURE on error
615 */
sip_del_myvia(sip_ticket_t * ticket)616 int sip_del_myvia (sip_ticket_t *ticket) {
617 osip_via_t *via;
618 int sts;
619
620 DEBUGC(DBCLASS_PROXY,"deleting topmost VIA");
621 via = osip_list_get (&(ticket->sipmsg->vias), 0);
622
623 if ( via == NULL ) {
624 ERROR("Got empty VIA list - is your UA configured properly?");
625 return STS_FAILURE;
626 }
627
628 if ( is_via_local(via) == STS_FALSE ) {
629 ERROR("I'm trying to delete a VIA but it's not mine! host=%s",via->host);
630 return STS_FAILURE;
631 }
632
633 sts = osip_list_remove(&(ticket->sipmsg->vias), 0);
634 osip_via_free (via);
635 return STS_SUCCESS;
636 }
637
638
639 /*
640 * SIP_REWRITE_CONTACT
641 *
642 * rewrite the Contact header
643 *
644 * RETURNS
645 * STS_SUCCESS on success
646 * STS_FAILURE on error
647 */
sip_rewrite_contact(sip_ticket_t * ticket,int direction)648 int sip_rewrite_contact (sip_ticket_t *ticket, int direction) {
649 osip_message_t *sip_msg=ticket->sipmsg;
650 osip_contact_t *contact;
651 int i, j;
652 int replaced=0;
653
654 if (sip_msg == NULL) return STS_FAILURE;
655
656 /* at least one contact header present? */
657 osip_message_get_contact(sip_msg, 0, &contact);
658 if (contact == NULL) return STS_FAILURE;
659
660 /* loop for all existing contact headers in message */
661 for (j=0; contact != NULL; j++) {
662 osip_message_get_contact(sip_msg, j, &contact);
663 if (contact == NULL) break;
664 if (contact->url == NULL) continue;
665
666 DEBUGC(DBCLASS_PROXY, "trying to rewriting Contact header %s@%s",
667 (contact->url->username)? contact->url->username : "*NULL*",
668 (contact->url->host)? contact->url->host : "*NULL*");
669
670 /* search for an entry */
671 for (i=0;i<URLMAP_SIZE;i++){
672 if (urlmap[i].active == 0) continue;
673 if ((direction == DIR_OUTGOING) &&
674 (compare_url(contact->url, urlmap[i].true_url)==STS_SUCCESS)) break;
675 if ((direction == DIR_INCOMING) &&
676 (compare_url(contact->url, urlmap[i].masq_url)==STS_SUCCESS)) break;
677 }
678
679 /* found a mapping entry */
680 if (i<URLMAP_SIZE) {
681 char *tmp;
682
683 if (direction == DIR_OUTGOING) {
684 DEBUGC(DBCLASS_PROXY, "rewriting Contact header %s@%s -> %s@%s",
685 (contact->url->username)? contact->url->username : "*NULL*",
686 (contact->url->host)? contact->url->host : "*NULL*",
687 urlmap[i].masq_url->username, urlmap[i].masq_url->host);
688 } else {
689 DEBUGC(DBCLASS_PROXY, "rewriting Contact header %s@%s -> %s@%s",
690 (contact->url->username)? contact->url->username : "*NULL*",
691 (contact->url->host)? contact->url->host : "*NULL*",
692 urlmap[i].true_url->username, urlmap[i].true_url->host);
693 }
694
695 /* remove old entry */
696 osip_list_remove(&(sip_msg->contacts),j);
697 osip_contact_to_str(contact, &tmp);
698 osip_contact_free(contact);
699
700 /* clone the url from urlmap*/
701 osip_contact_init(&contact);
702 osip_contact_parse(contact,tmp);
703 osip_free(tmp);
704 osip_uri_free(contact->url);
705 if (direction == DIR_OUTGOING) {
706 /* outgoing, use masqueraded url */
707 osip_uri_clone(urlmap[i].masq_url, &contact->url);
708 } else {
709 /* incoming, use true url */
710 osip_uri_clone(urlmap[i].true_url, &contact->url);
711 }
712
713 /* add transport=tcp parameter if TCP */
714 if (ticket->protocol == PROTO_TCP) {
715 osip_uri_set_transport_tcp(contact->url);
716 }
717
718 osip_list_add(&(sip_msg->contacts),contact,j);
719 replaced=1;
720 } else {
721 #if 1
722 /* FALLBACK - some devices send crappy Contact headers that
723 * are completely different from the Contact used in REGISTER.
724 * This is a hack-around, trying *somehow* to produce a "meaningful"
725 * masqueraded contact header (at least it does point back to the proxy
726 * and not into some RFC1918 network).
727 */
728 if (direction == DIR_OUTGOING) {
729 DEBUGC(DBCLASS_PROXY, "outgoing: no match - fallback to plain proxy IP");
730 struct in_addr addr;
731 if (get_interface_ip(IF_OUTBOUND, &addr) == STS_SUCCESS) {
732 char *myaddr;
733 myaddr=utils_inet_ntoa(addr);
734
735 /* Host */
736 osip_free(contact->url->host);
737 contact->url->host = osip_strdup(myaddr);
738 /* Port */
739 contact->url->port=realloc(contact->url->port, 16);
740 sprintf(contact->url->port, "%i", configuration.sip_listen_port);
741
742 replaced=1;
743 }
744 } // if direction
745 #endif
746 }
747
748 } /* for j */
749
750 if (replaced == 0) {
751 DEBUGC(DBCLASS_PROXY, "no Contact header rewritten!");
752 return STS_FAILURE;
753 }
754
755 return STS_SUCCESS;
756 }
757
758
759 /*
760 * SIP_CALCULATE_BRANCH
761 *
762 * Calculates a branch parameter according to RFC3261 section 16.11
763 *
764 * The returned 'id' will be HASHHEXLEN + strlen(magic_cookie)
765 * characters (32 + 7) long. The caller must supply at least this
766 * amount of space in 'id'.
767 *
768 * RETURNS
769 * STS_SUCCESS on success
770 * STS_FAILURE on error
771 */
sip_calculate_branch_id(sip_ticket_t * ticket,char * id)772 int sip_calculate_branch_id (sip_ticket_t *ticket, char *id) {
773 /* RFC3261 section 16.11 recommends the following procedure:
774 * The stateless proxy MAY use any technique it likes to guarantee
775 * uniqueness of its branch IDs across transactions. However, the
776 * following procedure is RECOMMENDED. The proxy examines the
777 * branch ID in the topmost Via header field of the received
778 * request. If it begins with the magic cookie, the first
779 * component of the branch ID of the outgoing request is computed
780 * as a hash of the received branch ID. Otherwise, the first
781 * component of the branch ID is computed as a hash of the topmost
782 * Via, the tag in the To header field, the tag in the From header
783 * field, the Call-ID header field, the CSeq number (but not
784 * method), and the Request-URI from the received request. One of
785 * these fields will always vary across two different
786 * transactions.
787 *
788 * The branch value will consist of:
789 * - magic cookie "z9hG4bK"
790 * - 1st part (unique calculated ID
791 * - 2nd part (value for loop detection) <<- not yet used by siproxd
792 */
793 osip_message_t *sip_msg=ticket->sipmsg;
794 static char *magic_cookie="z9hG4bK";
795 osip_via_t *via;
796 osip_uri_param_t *param=NULL;
797 osip_call_id_t *call_id=NULL;
798 HASHHEX hashstring;
799
800 hashstring[0]='\0';
801
802 /*
803 * Examine topmost via and look for a magic cookie.
804 * If it is there, I use THIS branch parameter as input for
805 * our hash calculation
806 */
807 via = osip_list_get (&(sip_msg->vias), 0);
808 if (via == NULL) {
809 ERROR("have a SIP message without any via header");
810 return STS_FAILURE;
811 }
812
813 param=NULL;
814 osip_via_param_get_byname(via, "branch", ¶m);
815 if (param && param->gvalue) {
816 DEBUGC(DBCLASS_BABBLE, "looking for magic cookie [%s]",param->gvalue);
817 if (strncmp(param->gvalue, magic_cookie,
818 strlen(magic_cookie))==0) {
819 /* calculate MD5 hash */
820 osip_MD5_CTX Md5Ctx;
821 HASH HA1;
822
823 osip_MD5Init(&Md5Ctx);
824 osip_MD5Update(&Md5Ctx, (unsigned char*)param->gvalue,
825 strlen(param->gvalue));
826 osip_MD5Final(HA1, &Md5Ctx);
827 CvtHex(HA1, hashstring);
828
829 DEBUGC(DBCLASS_BABBLE, "existing branch -> branch hash [%s]",
830 hashstring);
831 }
832 }
833
834 /*
835 * If I don't have a branch parameter in the existing topmost via,
836 * then I need:
837 * - the topmost via
838 * - the tag in the To header field
839 * - the tag in the From header field
840 * - the Call-ID header field
841 * - the CSeq number (but not method)
842 * - the Request-URI from the received request
843 */
844 if (hashstring[0] == '\0') {
845 /* calculate MD5 hash */
846 osip_MD5_CTX Md5Ctx;
847 HASH HA1;
848 char *tmp;
849
850 osip_MD5Init(&Md5Ctx);
851
852 /* topmost via */
853 osip_via_to_str(via, &tmp);
854 if (tmp) {
855 osip_MD5Update(&Md5Ctx, (unsigned char*)tmp, strlen(tmp));
856 osip_free(tmp);
857 }
858
859 /* Tag in To header */
860 osip_to_get_tag(sip_msg->to, ¶m);
861 if (param && param->gvalue) {
862 osip_MD5Update(&Md5Ctx, (unsigned char*)param->gvalue,
863 strlen(param->gvalue));
864 }
865
866 /* Tag in From header */
867 osip_from_get_tag(sip_msg->from, ¶m);
868 if (param && param->gvalue) {
869 osip_MD5Update(&Md5Ctx, (unsigned char*)param->gvalue,
870 strlen(param->gvalue));
871 }
872
873 /* Call-ID */
874 call_id = osip_message_get_call_id(sip_msg);
875 osip_call_id_to_str(call_id, &tmp);
876 if (tmp) {
877 osip_MD5Update(&Md5Ctx, (unsigned char*)tmp, strlen(tmp));
878 osip_free(tmp);
879 }
880
881 /* CSeq number (but not method) */
882 tmp = osip_cseq_get_number(sip_msg->cseq);
883 if (tmp) {
884 osip_MD5Update(&Md5Ctx, (unsigned char*)tmp, strlen(tmp));
885 }
886
887 /* Request URI */
888 osip_uri_to_str(sip_msg->req_uri, &tmp);
889 if (tmp) {
890 osip_MD5Update(&Md5Ctx, (unsigned char*)tmp, strlen(tmp));
891 osip_free(tmp);
892 }
893
894 osip_MD5Final(HA1, &Md5Ctx);
895 CvtHex(HA1, hashstring);
896
897 DEBUGC(DBCLASS_BABBLE, "non-existing branch -> branch hash [%s]",
898 hashstring);
899 }
900
901 /* include the magic cookie */
902 sprintf(id, "%s%s", magic_cookie, hashstring);
903
904 return STS_SUCCESS;
905 }
906
907
908 /*
909 * SIP_FIND_OUTBOUND_PROXY
910 *
911 * performs the lookup for an apropriate outbound proxy
912 *
913 * RETURNS
914 * STS_SUCCESS on successful lookup
915 * STS_FAILURE if no outbound proxy to be used
916 */
sip_find_outbound_proxy(sip_ticket_t * ticket,struct in_addr * addr,in_port_t * port)917 int sip_find_outbound_proxy(sip_ticket_t *ticket, struct in_addr *addr,
918 in_port_t *port) {
919 int i, sts;
920 char *domain=NULL;
921 osip_message_t *sipmsg;
922
923 sipmsg=ticket->sipmsg;
924
925 if (!addr ||!port) {
926 ERROR("sip_find_outbound_proxy called with NULL addr or port");
927 return STS_FAILURE;
928 }
929
930 if (sipmsg && sipmsg->from && sipmsg->from->url) {
931 domain=sipmsg->from->url->host;
932 }
933
934 if (domain == NULL) {
935 WARN("sip_find_outbound_proxy called with NULL from->url->host");
936 return STS_FAILURE;
937 }
938
939 /*
940 * check consistency of configuration:
941 * outbound_domain_name, outbound_domain_host, outbound_domain_port
942 * must match up
943 */
944 if ((configuration.outbound_proxy_domain_name.used !=
945 configuration.outbound_proxy_domain_host.used) ||
946 (configuration.outbound_proxy_domain_name.used !=
947 configuration.outbound_proxy_domain_port.used)) {
948 ERROR("configuration of outbound_domain_ inconsistent, check config");
949 } else {
950 /*
951 * perform the lookup for domain specific proxies
952 * first match wins
953 */
954 for (i=0; i<configuration.outbound_proxy_domain_name.used; i++) {
955 if (strcasecmp(configuration.outbound_proxy_domain_name.string[i],
956 domain)==0) {
957 sts = get_ip_by_host(configuration.outbound_proxy_domain_host.string[i],
958 addr);
959 if (sts == STS_FAILURE) {
960 ERROR("sip_find_outbound_proxy: cannot resolve "
961 "outbound proxy host [%s], check config",
962 configuration.outbound_proxy_domain_host.string[i]);
963 return STS_FAILURE;
964 }
965 *port=atoi(configuration.outbound_proxy_domain_port.string[i]);
966 // if ((*port<=0) || (*port>65535)) *port=SIP_PORT;
967
968 return STS_SUCCESS;
969
970 } /* strcmp */
971 } /* for i */
972 }
973
974 /*
975 * now check for a global outbound proxy
976 */
977 if (configuration.outbound_proxy_host) {
978 /* I have a global outbound proxy configured */
979 sts = get_ip_by_host(configuration.outbound_proxy_host, addr);
980 if (sts == STS_FAILURE) {
981 DEBUGC(DBCLASS_PROXY, "proxy_request: cannot resolve outbound "
982 " proxy host [%s]", configuration.outbound_proxy_host);
983 return STS_FAILURE;
984 }
985
986 if (configuration.outbound_proxy_port) {
987 *port=configuration.outbound_proxy_port;
988 } else {
989 *port = SIP_PORT;
990 }
991 DEBUGC(DBCLASS_PROXY, "proxy_request: have outbound proxy %s:%i",
992 configuration.outbound_proxy_host, *port);
993
994 return STS_SUCCESS;
995 }
996
997 return STS_FAILURE; /* no proxy */
998 }
999
1000
1001 /*
1002 * SIP_FIND_DIRECTION
1003 *
1004 * Figures out if this is an outgoing or incoming request/response.
1005 * The direction is stored in the ticket->direction property.
1006 *
1007 * RETURNS
1008 * STS_SUCCESS on success
1009 * STS_FAILURE if unable to determine
1010 */
sip_find_direction(sip_ticket_t * ticket,int * urlidx)1011 int sip_find_direction(sip_ticket_t *ticket, int *urlidx) {
1012 int type;
1013 int i, sts;
1014 struct sockaddr_in *from;
1015 osip_message_t *request;
1016 osip_message_t *response;
1017 struct in_addr tmp_addr, tmp_addr2;
1018
1019 from=&ticket->from;
1020 request=ticket->sipmsg;
1021 response=ticket->sipmsg;
1022 type = DIRTYP_UNKNOWN;
1023
1024 ticket->direction = DIRTYP_UNKNOWN;
1025
1026 DEBUGC(DBCLASS_SIP, "sip_find_direction: beginning search");
1027
1028 /* Search order is as follows:
1029 * - "from" IP address is one of our registered local UAs
1030 * => OUTGOING
1031 * - "Req: To:" SIP header (Request) directed to internal UA
1032 * or
1033 * Resp: "From:" SIP header (Response) coming from internal UA
1034 * => INCOMING
1035 * - Req: SIP URI matches one of the registered local UAs
1036 * => INCOMING
1037 * - Resp: check for bottommost "Via:" header to be
1038 * one of our registered local UA IPs
1039 * => INCOMING
1040 * - "from" IP == (127.0.0.1 | inbound_IP | outbound IP)
1041 * => OUTGOING
1042 *
1043 * The first successful match is taken.
1044 */
1045
1046 /*
1047 * did I receive the telegram from a REGISTERED host?
1048 * -> it must be an OUTGOING request/response
1049 */
1050 for (i=0; i<URLMAP_SIZE; i++) {
1051 if (urlmap[i].active == 0) continue;
1052 if (get_ip_by_host(urlmap[i].true_url->host, &tmp_addr) == STS_FAILURE) {
1053 DEBUGC(DBCLASS_SIP, "sip_find_direction: cannot resolve host [%s]",
1054 urlmap[i].true_url->host);
1055 } else {
1056 // DEBUGC(DBCLASS_BABBLE, "sip_find_direction: reghost:%s ip:%s",
1057 // urlmap[i].true_url->host, utils_inet_ntoa(from->sin_addr));
1058 if (memcmp(&tmp_addr, &from->sin_addr, sizeof(tmp_addr)) == 0) {
1059 if (MSG_IS_REQUEST(ticket->sipmsg)) {
1060 type=REQTYP_OUTGOING;
1061 } else {
1062 type=RESTYP_OUTGOING;
1063 }
1064 break;
1065 }
1066 }
1067 }
1068 if (type == DIRTYP_UNKNOWN) {
1069 DEBUGC(DBCLASS_SIP, "sip_find_direction: no OUTGOING found");
1070 }
1071
1072
1073 /*
1074 * is the telegram directed to an internally registered host?
1075 * -> likely to be an INCOMING request/response
1076 * check for a match on the To: header first
1077 */
1078 if (type == DIRTYP_UNKNOWN) {
1079 for (i=0; i<URLMAP_SIZE; i++) {
1080 if (urlmap[i].active == 0) continue;
1081 /* RFC3261:
1082 * 'To' contains a display name (Bob) and a SIP or SIPS URI
1083 * (sip:bob@biloxi.com) towards which the request was originally
1084 * directed. Display names are described in RFC 2822 [3].
1085 */
1086
1087 /* So this means, that we must check the SIP URI supplied with the
1088 * INVITE method, as this points to the real wanted target.
1089 * First we will try to match on the To: and From: headers
1090 * If nothing is found here, we try again with SIP URI futher down.
1091 */
1092
1093 if (MSG_IS_REQUEST(ticket->sipmsg)) {
1094 /* REQUEST */
1095 /* incoming request ('to' == 'masq') || (('to' == 'reg') && !REGISTER)*/
1096 if ((compare_url(request->to->url, urlmap[i].masq_url)==STS_SUCCESS) ||
1097 (!MSG_IS_REGISTER(request) &&
1098 (compare_url(request->to->url, urlmap[i].reg_url)==STS_SUCCESS))) {
1099 type=REQTYP_INCOMING;
1100 break;
1101 }
1102 } else {
1103 /* RESPONSE */
1104 /* incoming response ('from' == 'masq') || ('from' == 'reg') */
1105 if ((compare_url(response->from->url, urlmap[i].reg_url)==STS_SUCCESS) ||
1106 (compare_url(response->from->url, urlmap[i].masq_url)==STS_SUCCESS)) {
1107 type=RESTYP_INCOMING;
1108 break;
1109 }
1110 } /* is request */
1111 } /* for i */
1112 } /* if type == DIRTYP_UNKNOWN */
1113 if (type == DIRTYP_UNKNOWN) {
1114 DEBUGC(DBCLASS_SIP, "sip_find_direction: no INCOMING (To:) found");
1115 }
1116
1117
1118 /*
1119 * nothing found yet?
1120 * -> likely to be an INCOMING request/response
1121 * check for a match on the SIP URI (requests only)
1122 */
1123 if ((type == DIRTYP_UNKNOWN) && (MSG_IS_REQUEST(ticket->sipmsg))) {
1124 for (i=0; i<URLMAP_SIZE; i++) {
1125 if (urlmap[i].active == 0) continue;
1126 /* incoming request (SIP URI == 'masq') || ((SIP URI == 'reg') && !REGISTER)*/
1127 if ((compare_url(request->req_uri, urlmap[i].masq_url)==STS_SUCCESS) ||
1128 (!MSG_IS_REGISTER(request) &&
1129 (compare_url(request->req_uri, urlmap[i].reg_url)==STS_SUCCESS))) {
1130 type=REQTYP_INCOMING;
1131 break;
1132 }
1133 } /* for i */
1134 } /* if type == DIRTYP_UNKNOWN */
1135 if (type == DIRTYP_UNKNOWN) {
1136 DEBUGC(DBCLASS_SIP, "sip_find_direction: no INCOMING RQ (SIP URI) found");
1137 }
1138
1139
1140 /* &&&& Open Issue &&&&
1141 * it has been seen with cross-provider calls that the FROM may be 'garbled'
1142 * (e.g 1393xxx@proxy01.sipphone.com for calls made sipphone -> FWD)
1143 * How can we deal with this? Should I take into consideration the 'Via'
1144 * headers? This is the only clue I have, pointing to the *real* UA.
1145 * Maybe I should put in a 'siproxd' flag value to recognize it as a header
1146 * inserted by myself
1147 */
1148 if ((type == DIRTYP_UNKNOWN) &&
1149 (!osip_list_eol(&(response->vias), 1))) {
1150 if (MSG_IS_RESPONSE(ticket->sipmsg)) {
1151 osip_via_t *via;
1152 struct in_addr addr_via, addr_myself;
1153 int port_via, port_ua;
1154
1155 /* get the via address :
1156 * topmost via (pos 0) still is my own via (not yet removed)
1157 * next vi a(pos 1) may be local UA via
1158 */
1159 via = (osip_via_t *) osip_list_get (&(response->vias), 1);
1160 if (via) {
1161 DEBUGC(DBCLASS_SIP, "sip_find_direction: check via [%s] for "
1162 "registered UA",via->host);
1163 sts=get_ip_by_host(via->host, &addr_via);
1164 if (sts == STS_FAILURE) {
1165 DEBUGC(DBCLASS_SIP, "sip_find_direction: cannot resolve VIA [%s]",
1166 via->host);
1167 }
1168 } else {
1169 DEBUGC(DBCLASS_SIP, "sip_find_direction: no second via in list");
1170 sts = STS_FAILURE;
1171 }
1172
1173
1174 if (sts == STS_SUCCESS) {
1175 for (i=0; i<URLMAP_SIZE; i++) {
1176 if (urlmap[i].active == 0) continue;
1177 /* incoming response (1st via in list points to a registered UA) */
1178 sts=get_ip_by_host(urlmap[i].true_url->host, &addr_myself);
1179 if (sts == STS_FAILURE) {
1180 DEBUGC(DBCLASS_SIP, "sip_find_direction: cannot resolve "
1181 "true_url [%s]", via->host);
1182 continue;
1183 }
1184
1185 port_via=0;
1186 if (via->port) port_via=atoi(via->port);
1187 if ((port_via<=0) || (port_via>65535)) port_via=SIP_PORT;
1188
1189 port_ua=0;
1190 if (urlmap[i].true_url->port)
1191 port_ua=atoi(urlmap[i].true_url->port);
1192 if ((port_ua<=0) || (port_ua>65535)) port_ua=SIP_PORT;
1193
1194 DEBUGC(DBCLASS_BABBLE, "sip_find_direction: checking for registered "
1195 "host [%s:%i] <-> [%s:%i]",
1196 urlmap[i].true_url->host, port_ua,
1197 via->host, port_via);
1198
1199 if ((memcmp(&addr_myself, &addr_via, sizeof(addr_myself))==0) &&
1200 (port_via == port_ua)) {
1201 type=RESTYP_INCOMING;
1202 break;
1203 }
1204 } /* for i */
1205 }
1206 } /* is response */
1207 } /* if type == DIRTYP_UNKNOWN */
1208 if (type == DIRTYP_UNKNOWN) {
1209 DEBUGC(DBCLASS_SIP, "sip_find_direction: no INCOMING RS (via header) found");
1210 }
1211
1212
1213 /*
1214 * if the telegram is received from 127.0.0.1 use my inbound IP as sender,
1215 * this likely is a locally REDIRECTED/DNATed (by iptables) packet.
1216 * So it is a local UA.
1217 * Also, my own outbound address is considered to be redirected traffic
1218 * Example Scenario:
1219 * Softphone(or PBX) running on the same host as siproxd is running.
1220 * Using iptables, you do a REDIRECT of outgoing SIP traffic of the
1221 * PBX to be passed to siproxd.
1222 */
1223 if (type == DIRTYP_UNKNOWN) {
1224 sts=get_interface_ip(IF_INBOUND, &tmp_addr);
1225 sts=get_interface_ip(IF_OUTBOUND, &tmp_addr2);
1226 if ((htonl(from->sin_addr.s_addr) == INADDR_LOOPBACK) ||
1227 (from->sin_addr.s_addr == tmp_addr.s_addr) ||
1228 (from->sin_addr.s_addr == tmp_addr2.s_addr)) {
1229 if (MSG_IS_REQUEST(ticket->sipmsg)) {
1230 type=REQTYP_OUTGOING;
1231 } else {
1232 type=RESTYP_OUTGOING;
1233 }
1234 }
1235 } /* if type == DIRTYP_UNKNOWN */
1236 if (type == DIRTYP_UNKNOWN) {
1237 DEBUGC(DBCLASS_SIP, "sip_find_direction: no INCOMING (redirected) found");
1238 }
1239
1240
1241 if (type == DIRTYP_UNKNOWN) {
1242 DEBUGC(DBCLASS_SIP, "sip_find_direction: unable to determine "
1243 "direction of SIP packet");
1244 if (urlidx) *urlidx=-1;
1245 return STS_FAILURE;
1246 }
1247
1248 ticket->direction=type;
1249
1250 if (i < URLMAP_SIZE) {
1251 if (urlidx) *urlidx=i;
1252 DEBUGC(DBCLASS_SIP, "sip_find_direction: dir=%i, urlmap %i, "
1253 "trueurl [%s:%s] / masqurl [%s:%s] / regurl [%s:%s]",
1254 type, i,
1255 urlmap[i].true_url->host, urlmap[i].true_url->port,
1256 urlmap[i].masq_url->host, urlmap[i].masq_url->port,
1257 urlmap[i].reg_url->host, urlmap[i].reg_url->port);
1258 } else {
1259 if (urlidx) *urlidx=-1;
1260 DEBUGC(DBCLASS_SIP, "sip_find_direction: dir=%i, not found in URLMAP", type);
1261 }
1262 return STS_SUCCESS;
1263 }
1264
1265
1266 /*
1267 * SIP_FIXUP_ALERT_INFO
1268 *
1269 * Asterisk Hack.
1270 * Asterisk seems to include broken Alert-Info headers (without <>)
1271 * that cause parsing to fail (libosip2).
1272 * This function does try to guess if we have such a broken SIP
1273 * message and does simply remove the offending Alert-Info header.
1274 *
1275 * RETURNS
1276 * STS_SUCCESS on success
1277 */
sip_fixup_asterisk(char * buff,size_t * buflen)1278 int sip_fixup_asterisk(char *buff, size_t *buflen) {
1279 char *alert_info_ptr=NULL;
1280 /*
1281 * Check for Asterisk UA string
1282 * User-Agent: Asterisk PBX
1283 */
1284 if (strstr(buff, "\r\nUser-Agent: Asterisk PBX\r\n")==NULL)
1285 return STS_SUCCESS;
1286
1287 DEBUGC(DBCLASS_SIP, "sip_fixup_alert_info: SIP message is from Asterisk");
1288 /*
1289 * Look form Alert-Info: header
1290 */
1291 alert_info_ptr=strstr(buff, "\r\nAlert-Info: ");
1292 if (alert_info_ptr) {
1293 char *eol_ptr=NULL;
1294 DEBUGC(DBCLASS_SIP, "sip_fixup_alert_info: Asterisk message "
1295 "with Alert-Info found");
1296 eol_ptr=strstr((alert_info_ptr+2), "\r\n");
1297 if (eol_ptr) {
1298 int i;
1299 // cut the Alert-Info header from the message
1300 // (actually move the rest of the message up)
1301 DEBUGC(DBCLASS_SIP, "sip_fixup_alert_info: removed malformed "
1302 "Alert-Info header");
1303 for (i=0; i<(*buflen - (eol_ptr - buff)); i++) {
1304 alert_info_ptr[i]=eol_ptr[i];
1305 } /* for */
1306
1307 *buflen=strlen(buff);
1308 } /* if */
1309 }
1310 return STS_SUCCESS;
1311 }
1312
1313
1314 /*
1315 * SIP_OBSCURE_CALLID
1316 *
1317 27-May-2007: - new feature: "Obscure Loops" does modify the Call-IDs in
1318 outgoing requests and thus allows incoming calls forked
1319 off such an outgoing call (redirect, transfer, ...) back
1320 to the same UA where the initial call did originate.
1321 This even seems to fix some issues with Asterisks
1322 Loop detection... :-)
1323 Needs more thinking. The logic about call termination is quite tricky -
1324 calls can be terminated from either side... It is not stratigh forward
1325 when and how to modify CIDs for call cancellation...
1326 * ...
1327 *
1328 * RETURNS
1329 * STS_SUCCESS on success
1330 */
sip_obscure_callid(sip_ticket_t * ticket)1331 int sip_obscure_callid(sip_ticket_t *ticket) {
1332 static char myident[]="-siproxd";
1333 int myidentlen=sizeof(myident)-1; /* a static strlen() of myident */
1334
1335 osip_message_t *sipmsg;
1336 osip_from_t *from;
1337 osip_to_t *to;
1338 osip_uri_param_t *fromtag, *totag; /* gname, gvalue */
1339
1340 osip_call_id_t *CID=NULL;
1341
1342 char *tmp, *tmp2;
1343
1344
1345 /* feature enabled? */
1346 if (!configuration.obscure_loops) return STS_SUCCESS;
1347
1348 sipmsg=ticket->sipmsg;
1349
1350
1351 if (MSG_IS_REQUEST(sipmsg) &&
1352 MSG_IS_REGISTER(sipmsg)) return STS_SUCCESS;
1353 if (MSG_IS_RESPONSE(sipmsg) &&
1354 MSG_IS_RESPONSE_FOR(sipmsg,"REGISTER")) return STS_SUCCESS;
1355
1356 from=sipmsg->from;
1357 osip_from_get_tag(from, &fromtag);
1358
1359 to=sipmsg->to;
1360 osip_to_get_tag(to, &totag);
1361
1362 /* at lest the From Tag must be present, otherwise out Logic does
1363 not work. Is MANDATORY according to RFC3261 */
1364 if (!fromtag || !fromtag->gvalue || strlen(fromtag->gvalue)==0) {
1365 WARN("sip_obscure_callid: no From-Tag, not RFC3261 conform!");
1366 return STS_FAILURE;
1367 }
1368
1369 CID=osip_message_get_call_id(sipmsg);
1370
1371 /* does CID->number exist? According to RFC3261, this part is mandatory */
1372 if (!CID || !CID->number) {
1373 WARN("sip_obscure_callid: invalid Call-ID received, not RFC3261 conform!");
1374 return STS_FAILURE;
1375 }
1376
1377 DEBUGC(DBCLASS_PROXY, "sip_obscure_callid: current Callid#=%s Direction=%i",
1378 CID->number, ticket->direction);
1379
1380 switch (ticket->direction) {
1381
1382 /* Outgoing Request */
1383 case REQTYP_OUTGOING:
1384 /* also need testing for "normal" incoming call that is present and
1385 now we SEND a cancel for this call */
1386 tmp=strstr(CID->number, myident);
1387 if (tmp==NULL) {
1388 /* no obscuring present yet, must be a new call, modify it */
1389 tmp=osip_malloc(strlen(CID->number) + myidentlen +
1390 strlen(fromtag->gvalue) + 1);
1391 sprintf(tmp,"%s%s%s",CID->number,myident,fromtag->gvalue);
1392 osip_free(CID->number);
1393 CID->number=tmp;
1394 } else {
1395 /* Obscuring is present, do nothing. */
1396 }
1397 break;
1398
1399 /* Incoming Response */
1400 case RESTYP_INCOMING:
1401 tmp=strstr(CID->number,myident);
1402 /* modify it back if existing */
1403 if (tmp) {
1404 /* make sure to cut only the last marker - in case
1405 of multiple siproxd instances...
1406 I dont know if this actually would work (multiple instances...)*/
1407 for (;(tmp2=strstr(tmp+1, myident)) != NULL;) {
1408 tmp=tmp2;
1409 }
1410 tmp[0]='\0';
1411 }
1412 break;
1413
1414 /* Incoming Request */
1415 case REQTYP_INCOMING:
1416 tmp=strstr(CID->number, myident);
1417 if (tmp==NULL) {
1418 /* no obscuring present yet, must be a new incoming call, do nothing */
1419 } else {
1420 /* if BYE or CANCEL, check if obscuring present.
1421 * if From-Tag different than in CID stored, modify back CID */
1422 DEBUGC(DBCLASS_PROXY, "tmp+myidentlen=[%s], FromTag=[%s]",
1423 tmp+myidentlen, fromtag->gvalue);
1424
1425 if (strcmp(tmp+myidentlen, fromtag->gvalue) != 0) {
1426 tmp[0]='\0';
1427 } else {
1428 /* if From-Tag equal to in CID stored, do nothing */
1429 }
1430 }
1431 break;
1432
1433 /* Outgoing Response */
1434 case RESTYP_OUTGOING:
1435 if (MSG_IS_RESPONSE_FOR(sipmsg,"BYE")) {
1436 tmp=strstr(CID->number, myident);
1437 if ((tmp==NULL)&& totag && totag->gvalue) {
1438 /* no obscuring present yet, must be a new call, modify it */
1439 tmp=osip_malloc(strlen(CID->number) + myidentlen +
1440 strlen(fromtag->gvalue) + 1);
1441 sprintf(tmp,"%s%s%s",CID->number,myident,totag->gvalue);
1442 osip_free(CID->number);
1443 CID->number=tmp;
1444 } else {
1445 /* Obscuring is present, do nothing. */
1446 }
1447 }
1448 // tmp=strstr(CID->number, myident);
1449 // /* modify it back if existing*/
1450 // if (tmp) {
1451 // /* make sure to cut only the last marker - in case
1452 // of multiple siproxd instances... */
1453 // for (;(tmp2=strstr(tmp+1, myident)) != NULL;) {
1454 // tmp=tmp2;
1455 // }
1456 // tmp[0]='\0';
1457 // }
1458 break;
1459
1460 }
1461
1462 DEBUGC(DBCLASS_PROXY, "sip_obscure_callid: new Callid#=%s",CID->number);
1463
1464 return STS_SUCCESS;
1465 }
1466
1467
1468 /*
1469 * SIP_ADD_RECEIVED_PARAM
1470 *
1471 * Add a received parameter to the topmost VIA header (IP and port)
1472 *
1473 * RETURNS
1474 * STS_SUCCESS on success
1475 */
sip_add_received_param(sip_ticket_t * ticket)1476 int sip_add_received_param(sip_ticket_t *ticket){
1477 osip_via_t *via;
1478 char tmp[6];
1479
1480 DEBUGC(DBCLASS_PROXY,"adding received= param to topmost via");
1481 via = osip_list_get (&(ticket->sipmsg->vias), 0);
1482
1483 /* set rport=xxx;received=1.2.3.4 */
1484 snprintf(tmp, sizeof(tmp), "%i", ntohs(ticket->from.sin_port));
1485 osip_via_param_add(via,osip_strdup("rport"),osip_strdup(tmp));
1486
1487 osip_via_param_add(via,osip_strdup("received"),
1488 osip_strdup(utils_inet_ntoa(ticket->from.sin_addr)));
1489
1490 return STS_SUCCESS;
1491 }
1492
1493
1494 /*
1495 * SIP_GET_RECEIVED_PARAM
1496 *
1497 * Get a received parameter from the topmost VIA header (IP and port)
1498 *
1499 * RETURNS
1500 * STS_SUCCESS on success
1501 */
sip_get_received_param(sip_ticket_t * ticket,struct in_addr * dest,in_port_t * port)1502 int sip_get_received_param(sip_ticket_t *ticket,
1503 struct in_addr *dest, in_port_t *port) {
1504 osip_via_t *via;
1505 osip_generic_param_t *received=NULL;
1506 osip_generic_param_t *rport=NULL;
1507 int sts;
1508
1509 DEBUGC(DBCLASS_PROXY,"searching received= param in topmost via");
1510 via = osip_list_get (&(ticket->sipmsg->vias), 0);
1511
1512 osip_via_param_get_byname (via, "received", &received);
1513 osip_via_param_get_byname (via, "rport", &rport);
1514
1515 if (received && rport && received->gvalue && rport->gvalue) {
1516 /* fetch the IP */
1517 sts = get_ip_by_host(received->gvalue, dest);
1518 if (sts != STS_SUCCESS) return STS_FAILURE;
1519
1520 /* fetch the port number */
1521 *port = atoi(rport->gvalue);
1522 // if ((*port <=0) || (*port >=65536)) return STS_FAILURE;
1523
1524 /* If TCP, then validate first if an existing connection is in the cache.
1525 * If not, do not use this - a new conection must be established! */
1526 if (ticket->protocol == PROTO_TCP) {
1527 struct sockaddr_in addr;
1528 addr.sin_family = AF_INET;
1529 memcpy(&addr.sin_addr, dest, sizeof(struct in_addr));
1530 addr.sin_port= htons(*port);
1531 sts = tcp_find(addr);
1532 if (sts < 0) {
1533 DEBUGC(DBCLASS_BABBLE, "IP: %s, port: %i not found in cache",
1534 utils_inet_ntoa(*dest), *port);
1535 return STS_FAILURE;
1536 }
1537 }
1538
1539 /* found, return */
1540 DEBUGC(DBCLASS_BABBLE, "IP:%s, port:%i is ok to be reused",
1541 utils_inet_ntoa(*dest), *port);
1542 return STS_SUCCESS;
1543 }
1544
1545 /* not found */
1546 return STS_FAILURE;
1547 }
1548