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:
Guus Sliepen 2000-05-27 19:04:12 +00:00
parent 4d71de15e8
commit e4ff969a98
3 changed files with 17 additions and 9 deletions

View file

@ -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.");
}

View file

@ -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;

View file

@ -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);