Fix for a DoS attack:
A remote user could telnet to the tinc daemon and type only this line: 61 6 00000000/00000000:28f This would deny any packets to be sent to other tinc networks (except for to the hosts that run tincd's themselves). Solution is to skip hosts in lookup_conn() that have not been activated yet. Fixed potential conn_list table corruption: If a new connection is accepted but a connection with the same subnet would already exist in the connection list, the OLD connection is terminated.
This commit is contained in:
parent
4d71de15e8
commit
e4ff969a98
3 changed files with 17 additions and 9 deletions
|
@ -821,8 +821,8 @@ cp
|
|||
|
||||
if(cl->status.outgoing)
|
||||
{
|
||||
alarm(5);
|
||||
signal(SIGALRM, sigalrm_handler);
|
||||
alarm(5);
|
||||
syslog(LOG_NOTICE, "Try to re-establish outgoing connection in 5 seconds.");
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,8 @@
|
|||
|
||||
/*
|
||||
look for a connection associated with the given vpn ip,
|
||||
return its connection structure
|
||||
return its connection structure.
|
||||
Skips connections that are not activated!
|
||||
*/
|
||||
conn_list_t *lookup_conn(ip_t ip)
|
||||
{
|
||||
|
@ -45,10 +46,10 @@ conn_list_t *lookup_conn(ip_t ip)
|
|||
cp
|
||||
/* Exact match suggested by James B. MacLean */
|
||||
for(p = conn_list; p != NULL; p = p->next)
|
||||
if(ip == p->vpn_ip)
|
||||
if((ip == p->vpn_ip) && p->active)
|
||||
return p;
|
||||
for(p = conn_list; p != NULL; p = p->next)
|
||||
if((ip & p->vpn_mask) == (p->vpn_ip & p->vpn_mask))
|
||||
if(((ip & p->vpn_mask) == (p->vpn_ip & p->vpn_mask)) && p->active)
|
||||
return p;
|
||||
cp
|
||||
return NULL;
|
||||
|
|
|
@ -188,7 +188,7 @@ void send_key_changed_all(void)
|
|||
conn_list_t *p;
|
||||
cp
|
||||
for(p = conn_list; p != NULL; p = p->next)
|
||||
if(p->status.meta && p->protocol_version > PROT_3)
|
||||
if(p->status.meta && p->active)
|
||||
send_key_changed(p, myself);
|
||||
cp
|
||||
}
|
||||
|
@ -332,7 +332,7 @@ int notify_others(conn_list_t *new, conn_list_t *source,
|
|||
conn_list_t *p;
|
||||
cp
|
||||
for(p = conn_list; p != NULL; p = p->next)
|
||||
if(p != new && p != source && p->status.meta)
|
||||
if(p != new && p != source && p->status.meta && p->active)
|
||||
function(p, new);
|
||||
cp
|
||||
return 0;
|
||||
|
@ -347,7 +347,7 @@ int notify_one(conn_list_t *new)
|
|||
conn_list_t *p;
|
||||
cp
|
||||
for(p = conn_list; p != NULL; p = p->next)
|
||||
if(p != new && p->protocol_version > PROT_3)
|
||||
if(p != new && p->active)
|
||||
send_add_host(new, p);
|
||||
cp
|
||||
return 0;
|
||||
|
@ -392,8 +392,6 @@ cp
|
|||
return -1;
|
||||
send_passphrase(cl);
|
||||
}
|
||||
|
||||
cl->status.active = 0;
|
||||
cp
|
||||
return 0;
|
||||
}
|
||||
|
@ -424,6 +422,7 @@ cp
|
|||
int public_key_h(conn_list_t *cl)
|
||||
{
|
||||
char *g_n;
|
||||
conn_list_t *old;
|
||||
cp
|
||||
if(sscanf(cl->buffer, "%*d %as", &g_n) != 1)
|
||||
{
|
||||
|
@ -449,6 +448,14 @@ cp
|
|||
else
|
||||
send_ack(cl);
|
||||
|
||||
/* Okay, before we active the connection, we check if there is another entry
|
||||
in the connection list with the same vpn_ip. If so, it presumably is an
|
||||
old connection that has timed out but we don't know it yet. Because our
|
||||
conn_list entry is not active, lookup_conn will skip ourself. */
|
||||
|
||||
if(old=lookup_conn(cl->vpn_ip))
|
||||
terminate_connection(old);
|
||||
|
||||
cl->status.active = 1;
|
||||
notify_others(cl, NULL, send_add_host);
|
||||
notify_one(cl);
|
||||
|
|
Loading…
Reference in a new issue