Always try next Address when an outgoing connection fails to authenticate.

When making outgoing connections, tinc goes through the list of Addresses and
tries all of them until one succeeds. However, before it would consider
establishing a TCP connection a success, even when the authentication failed.
This would be a problem if the first Address would point to a hostname and port
combination that belongs to the wrong tinc node, or perhaps even to a non-tinc
service, causing tinc to endlessly try this Address instead of moving to the
next one.

Problem found by Delf Eldkraft.
This commit is contained in:
Guus Sliepen 2012-03-20 23:49:16 +01:00
parent 28a1501b9a
commit 80e15d8b96
4 changed files with 42 additions and 29 deletions

View file

@ -60,44 +60,54 @@ connection_t *new_connection(void) {
return c;
}
void free_connection(connection_t *c) {
if(c->name)
free(c->name);
void free_connection_partially(connection_t *c) {
free(c->inkey);
free(c->outkey);
free(c->mychallenge);
free(c->hischallenge);
free(c->outbuf);
if(c->hostname)
free(c->hostname);
c->inkey = NULL;
c->outkey = NULL;
c->mychallenge = NULL;
c->hischallenge = NULL;
c->outbuf = NULL;
if(c->inkey)
free(c->inkey);
if(c->outkey)
free(c->outkey);
c->buflen = 0;
c->reqlen = 0;
c->tcplen = 0;
c->allow_request = 0;
c->outbuflen = 0;
c->outbufsize = 0;
c->outbufstart = 0;
if(c->inctx) {
EVP_CIPHER_CTX_cleanup(c->inctx);
free(c->inctx);
c->inctx = NULL;
}
if(c->outctx) {
EVP_CIPHER_CTX_cleanup(c->outctx);
free(c->outctx);
c->outctx = NULL;
}
if(c->mychallenge)
free(c->mychallenge);
if(c->rsa_key) {
RSA_free(c->rsa_key);
c->rsa_key = NULL;
}
}
if(c->hischallenge)
free(c->hischallenge);
void free_connection(connection_t *c) {
free_connection_partially(c);
free(c->name);
free(c->hostname);
if(c->config_tree)
exit_configuration(&c->config_tree);
if(c->outbuf)
free(c->outbuf);
if(c->rsa_key)
RSA_free(c->rsa_key);
free(c);
}

View file

@ -107,6 +107,7 @@ extern void init_connections(void);
extern void exit_connections(void);
extern connection_t *new_connection(void) __attribute__ ((__malloc__));
extern void free_connection(connection_t *);
extern void free_connection_partially(connection_t *);
extern void connection_add(connection_t *);
extern void connection_del(connection_t *);
extern void dump_connections(void);

View file

@ -204,18 +204,14 @@ void terminate_connection(connection_t *c, bool report) {
}
}
free_connection_partially(c);
/* Check if this was our outgoing connection */
if(c->outgoing) {
retry_outgoing(c->outgoing);
c->outgoing = NULL;
c->status.remove = false;
do_outgoing_connection(c);
}
free(c->outbuf);
c->outbuf = NULL;
c->outbuflen = 0;
c->outbufsize = 0;
c->outbufstart = 0;
}
/*

View file

@ -111,8 +111,14 @@ bool pong_h(connection_t *c) {
/* Succesful connection, reset timeout if this is an outgoing connection. */
if(c->outgoing)
if(c->outgoing) {
c->outgoing->timeout = 0;
c->outgoing->cfg = NULL;
if(c->outgoing->ai)
freeaddrinfo(c->outgoing->ai);
c->outgoing->ai = NULL;
c->outgoing->aip = NULL;
}
return true;
}