From 80e15d8b96e5313b33c91003b1f75d7f6db9924e Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Tue, 20 Mar 2012 23:49:16 +0100 Subject: [PATCH] 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. --- src/connection.c | 54 +++++++++++++++++++++++++++------------------ src/connection.h | 1 + src/net.c | 12 ++++------ src/protocol_misc.c | 8 ++++++- 4 files changed, 44 insertions(+), 31 deletions(-) diff --git a/src/connection.c b/src/connection.c index 612587dd..9b752fad 100644 --- a/src/connection.c +++ b/src/connection.c @@ -60,44 +60,54 @@ connection_t *new_connection(void) { return c; } -void free_connection(connection_t *c) { - if(c->name) - free(c->name); - - if(c->hostname) - free(c->hostname); - - if(c->inkey) - free(c->inkey); - - if(c->outkey) - free(c->outkey); +void free_connection_partially(connection_t *c) { + free(c->inkey); + free(c->outkey); + free(c->mychallenge); + free(c->hischallenge); + free(c->outbuf); + + c->inkey = NULL; + c->outkey = NULL; + c->mychallenge = NULL; + c->hischallenge = NULL; + c->outbuf = NULL; + + 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->rsa_key) { + RSA_free(c->rsa_key); + c->rsa_key = NULL; } +} - if(c->mychallenge) - free(c->mychallenge); +void free_connection(connection_t *c) { + free_connection_partially(c); - if(c->hischallenge) - free(c->hischallenge); + 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); } diff --git a/src/connection.h b/src/connection.h index 544c2d0b..fbe4e02c 100644 --- a/src/connection.h +++ b/src/connection.h @@ -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); diff --git a/src/net.c b/src/net.c index 6979083f..0496a864 100644 --- a/src/net.c +++ b/src/net.c @@ -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; } /* diff --git a/src/protocol_misc.c b/src/protocol_misc.c index 3d405bc4..8818d023 100644 --- a/src/protocol_misc.c +++ b/src/protocol_misc.c @@ -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; } -- 2.39.5