more changes around plugin_fix_fbox_anoncall and Contact Header masquerading
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+38
-16
@@ -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;i<URLMAP_SIZE;i++){
|
||||
if (urlmap[i].active == 0) continue;
|
||||
@@ -670,16 +676,6 @@ int sip_rewrite_contact (sip_ticket_t *ticket, int direction) {
|
||||
(compare_url(contact->url, 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 (i<URLMAP_SIZE) {
|
||||
char *tmp;
|
||||
@@ -721,6 +717,32 @@ int sip_rewrite_contact (sip_ticket_t *ticket, int direction) {
|
||||
|
||||
osip_list_add(&(sip_msg->contacts),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! */
|
||||
|
||||
+2
-2
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user