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", &param);
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, &param);
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, &param);
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