From d80848c760f4fb94193c467be97090c008835533 Mon Sep 17 00:00:00 2001 From: Thomas Ries Date: Wed, 3 Feb 2016 20:02:27 +0000 Subject: [PATCH] more changes around plugin_fix_fbox_anoncall and Contact Header masquerading --- src/plugin_fix_fbox_anoncall.c | 60 +++++++++++++++++++++++++--------- src/sip_utils.c | 54 +++++++++++++++++++++--------- src/utils.c | 4 +-- 3 files changed, 85 insertions(+), 33 deletions(-) diff --git a/src/plugin_fix_fbox_anoncall.c b/src/plugin_fix_fbox_anoncall.c index 34c8bcc..17457b3 100644 --- a/src/plugin_fix_fbox_anoncall.c +++ b/src/plugin_fix_fbox_anoncall.c @@ -107,21 +107,24 @@ int PLUGIN_PROCESS(int stage, sip_ticket_t *ticket){ type = ticket->direction; -DEBUGC(DBCLASS_PLUGIN, "plugin_fix_fbox_anoncall: type=%i", type); + DEBUGC(DBCLASS_PLUGIN, "plugin_fix_fbox_anoncall: type=%i", type); /* Outgoing SIP response? - may also need to process outgoing SIP requests - */ if ((type == RESTYP_OUTGOING) || (type == REQTYP_OUTGOING)) { /* a Contact header needs to be present in response */ osip_message_get_contact(ticket->sipmsg, 0, &contact); if(contact == NULL) { - DEBUGC(DBCLASS_PLUGIN, "no Contact header found in outgoing SIP message"); + DEBUGC(DBCLASS_PLUGIN, "no Contact header found in SIP message"); return STS_SUCCESS; } if(contact->url == NULL) { - DEBUGC(DBCLASS_PLUGIN, "no Contact->Url header found in outgoing SIP message"); + DEBUGC(DBCLASS_PLUGIN, "no Contact->url header found in SIP message"); + return STS_SUCCESS; + } + if (contact->url->host == NULL) { + DEBUGC(DBCLASS_PLUGIN, "no Contact->url->host header found in SIP message"); return STS_SUCCESS; } - /* @@ -158,6 +161,7 @@ DEBUGC(DBCLASS_PLUGIN, "plugin_fix_fbox_anoncall: type=%i", type); param_match=0; if (urlmap[idx].active == 0) continue; + if (urlmap[idx].true_url == NULL) continue; /* outgoing response - only look for true_url */ /* 1) check host, skip of no match */ @@ -167,18 +171,28 @@ DEBUGC(DBCLASS_PLUGIN, "plugin_fix_fbox_anoncall: type=%i", type); continue; } } + DEBUGC(DBCLASS_PLUGIN, "plugin_fix_fbox_anoncall: idx=%i, IP/Host match [%s]", + idx, contact->url->host); /* 2) check username match */ if (contact->url->username && urlmap[idx].true_url->username) { + DEBUGC(DBCLASS_PLUGIN, "plugin_fix_fbox_anoncall: check username: " + "contact->url->username [%s] <-> true_url->username [%s]", + contact->url->username, urlmap[idx].true_url->username); if (osip_strcasecmp(contact->url->username, urlmap[idx].true_url->username) == 0) { /* MATCH, all OK - return */ user_match=1; + DEBUGC(DBCLASS_PLUGIN, "plugin_fix_fbox_anoncall: username matches"); break; } + } else { + DEBUGC(DBCLASS_PLUGIN, "plugin_fix_fbox_anoncall: NULL username: " + "contact->username 0x%p <-> true_url->username 0x%p", + contact->url->username, urlmap[idx].true_url->username); } /* 3) check param field ("uniq=" param)*/ - if (contact->url && urlmap[idx].true_url) { + { int sts1, sts2; osip_uri_param_t *p1=NULL, *p2=NULL; @@ -186,12 +200,28 @@ DEBUGC(DBCLASS_PLUGIN, "plugin_fix_fbox_anoncall: type=%i", type); sts2=osip_uri_param_get_byname(&(urlmap[idx].true_url->url_params), "uniq", &p2); if ( ((sts1 == OSIP_SUCCESS) && (sts2 == OSIP_SUCCESS)) && (p1 && p2) && - (p1->gname && p2->gname && p1->gvalue && p2->gvalue) && - (osip_strcasecmp(p1->gname, p2->gname) == 0) && - (osip_strcasecmp(p1->gvalue, p2->gvalue) == 0) ) { - /* MATCH */ - param_match=1; - param_match_idx=idx; + (p1->gname && p2->gname && p1->gvalue && p2->gvalue) ) { + DEBUGC(DBCLASS_PLUGIN, "plugin_fix_fbox_anoncall: check param: " + "contact-> [%s]=[%s] <-> true_url->[%s]=[%s]", + p1->gname, p1->gvalue, p2->gname, p2->gvalue); + + if ((osip_strcasecmp(p1->gname, p2->gname) == 0) && + (osip_strcasecmp(p1->gvalue, p2->gvalue) == 0) ) { + /* MATCH */ + param_match=1; + param_match_idx=idx; + DEBUGC(DBCLASS_PLUGIN, "plugin_fix_fbox_anoncall: uniq param matches"); + } + } else { + if (p1 && p2) { + DEBUGC(DBCLASS_PLUGIN, "plugin_fix_fbox_anoncall: NULL param fields: " + "contact-> 0x%p=0x%p <-> true_url->0x%p=0x%p", + p1->gname, p1->gvalue, p2->gname, p2->gvalue); + } else { + DEBUGC(DBCLASS_PLUGIN, "plugin_fix_fbox_anoncall: NULL param: " + "contact->param 0x%p <-> true_url->param 0x%p", + p1, p2); + } } } @@ -205,9 +235,9 @@ DEBUGC(DBCLASS_PLUGIN, "plugin_fix_fbox_anoncall: type=%i", type); /* no partial match (no host, or no user / no param match) */ if (param_match == 0) { - WARN("Bogus outgoing response Contact header from [%s], unable to sanitize!", - utils_inet_ntoa(ticket->from.sin_addr)); - return STS_FAILURE; + DEBUGC(DBCLASS_PLUGIN, "Bogus outgoing response Contact header from [%s], " + "unable to sanitize!", utils_inet_ntoa(ticket->from.sin_addr)); + return STS_SUCCESS; } /* param_match - replace the username part from [param_match_idx] -> Contact */ @@ -224,7 +254,7 @@ DEBUGC(DBCLASS_PLUGIN, "plugin_fix_fbox_anoncall: type=%i", type); DEBUGC(DBCLASS_PLUGIN, "plugin_fix_fbox_anoncall: no IP match, returning."); } DEBUGC(DBCLASS_PLUGIN, "plugin_fix_fbox_anoncall: done"); - } // if (type == RESTYP_OUTGOING) + } // if (type == .. return STS_SUCCESS; } diff --git a/src/sip_utils.c b/src/sip_utils.c index 5993e4e..6c98f6f 100644 --- a/src/sip_utils.c +++ b/src/sip_utils.c @@ -270,6 +270,7 @@ int compare_url(osip_uri_t *url1, osip_uri_t *url2) { return STS_FAILURE; } +#if 0 DEBUGC(DBCLASS_BABBLE, "comparing urls: %s:%s@%s -> %s:%s@%s", (url1->scheme) ? url1->scheme : "(null)", (url1->username) ? url1->username : "(null)", @@ -277,6 +278,7 @@ int compare_url(osip_uri_t *url1, osip_uri_t *url2) { (url2->scheme) ? url2->scheme : "(null)", (url2->username) ? url2->username : "(null)", (url2->host) ? url2->host : "(null)"); +#endif /* compare SCHEME (if present) case INsensitive */ if (url1->scheme && url2->scheme) { @@ -291,11 +293,11 @@ int compare_url(osip_uri_t *url1, osip_uri_t *url2) { /* compare username (if present) case sensitive */ if (url1->username && url2->username) { if (strcmp(url1->username, url2->username) != 0) { - DEBUGC(DBCLASS_BABBLE, "compare_url: username mismatch"); +// DEBUGC(DBCLASS_BABBLE, "compare_url: username mismatch"); return STS_FAILURE; } } else { - DEBUGC(DBCLASS_BABBLE, "compare_url: NULL username - ignoring"); +// DEBUGC(DBCLASS_BABBLE, "compare_url: NULL username - ignoring"); } @@ -661,6 +663,10 @@ int sip_rewrite_contact (sip_ticket_t *ticket, int direction) { if (contact == NULL) break; if (contact->url == NULL) continue; + DEBUGC(DBCLASS_PROXY, "trying to rewriting Contact header %s@%s", + (contact->url->username)? contact->url->username : "*NULL*", + (contact->url->host)? contact->url->host : "*NULL*"); + /* search for an entry */ for (i=0;iurl, urlmap[i].masq_url)==STS_SUCCESS)) break; } - /* NOTE: - It has been observed with some UAs (e.g. Fritzbox) that when receiving - an anonymous call (call with supressed CLID) these UAs do send a *modified* - Contact header (compared to the Contact used in REGISTER). - This confuses siproxd as now masquerading cannot match the Contact Header - with the URLMAP table. - -> see plugin_fix_fbox_anoncall that tries to work around things by - detecting this and restoring the "sane" Contact header. - /* - /* found a mapping entry */ if (icontacts),contact,j); replaced=1; + } else { +#if 1 + /* FALLBACK - some devices send crappy Contact headers that + * are completely different from the Contact used in REGISTER. + * This is a hack-around, trying *somehow* to produce a "meaningful" + * masqueraded contact header (at least it does point back to the proxy + * and not into some RFC1918 network). + */ + if (direction == DIR_OUTGOING) { + DEBUGC(DBCLASS_PROXY, "outgoing: no match - fallback to plain proxy IP"); + struct in_addr addr; + if (get_interface_ip(IF_OUTBOUND, &addr) == STS_SUCCESS) { + char *myaddr; + myaddr=utils_inet_ntoa(addr); + + /* Host */ + osip_free(contact->url->host); + contact->url->host = osip_strdup(myaddr); + /* Port */ + contact->url->port=realloc(contact->url->port, 16); + sprintf(contact->url->port, "%i", configuration.sip_listen_port); + + replaced=1; + } + } // if direction +#endif } } /* for j */ @@ -941,7 +963,7 @@ int sip_find_outbound_proxy(sip_ticket_t *ticket, struct in_addr *addr, return STS_FAILURE; } *port=atoi(configuration.outbound_proxy_domain_port.string[i]); - if ((*port<=0) || (*port>65535)) *port=SIP_PORT; +// if ((*port<=0) || (*port>65535)) *port=SIP_PORT; return STS_SUCCESS; @@ -1029,8 +1051,8 @@ int sip_find_direction(sip_ticket_t *ticket, int *urlidx) { DEBUGC(DBCLASS_SIP, "sip_find_direction: cannot resolve host [%s]", urlmap[i].true_url->host); } else { - DEBUGC(DBCLASS_BABBLE, "sip_find_direction: reghost:%s ip:%s", - urlmap[i].true_url->host, utils_inet_ntoa(from->sin_addr)); +// DEBUGC(DBCLASS_BABBLE, "sip_find_direction: reghost:%s ip:%s", +// urlmap[i].true_url->host, utils_inet_ntoa(from->sin_addr)); if (memcmp(&tmp_addr, &from->sin_addr, sizeof(tmp_addr)) == 0) { if (MSG_IS_REQUEST(ticket->sipmsg)) { type=REQTYP_OUTGOING; @@ -1480,7 +1502,7 @@ int sip_get_received_param(sip_ticket_t *ticket, /* fetch the port number */ *port = atoi(rport->gvalue); - if ((*port <=0) || (*port >=65536)) return STS_FAILURE; +// if ((*port <=0) || (*port >=65536)) return STS_FAILURE; /* If TCP, then validate first if an existing connection is in the cache. * If not, do not use this - a new conection must be established! */ diff --git a/src/utils.c b/src/utils.c index c44f431..d284e4c 100644 --- a/src/utils.c +++ b/src/utils.c @@ -97,8 +97,8 @@ int get_ip_by_host(char *hostname, struct in_addr *addr) { /* check if passed string is already a plain IPv4 address */ if (utils_inet_aton(hostname, addr) > 0) { /* is a plain IPv4 string - return the result directly, no lookup and cache */ - DEBUGC(DBCLASS_BABBLE, "DNS lookup - shortcut, hostname is IP string [%s] -> [%s]", - hostname, utils_inet_ntoa(*addr)); +// DEBUGC(DBCLASS_BABBLE, "DNS lookup - shortcut, hostname is IP string [%s] -> [%s]", +// hostname, utils_inet_ntoa(*addr)); return STS_SUCCESS; }