Always try next Address when an outgoing connection fails to authenticate.
authorGuus Sliepen <guus@tinc-vpn.org>
Tue, 20 Mar 2012 22:49:16 +0000 (23:49 +0100)
committerGuus Sliepen <guus@tinc-vpn.org>
Tue, 20 Mar 2012 22:49:16 +0000 (23:49 +0100)
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
src/connection.h
src/net.c
src/protocol_misc.c

index 612587ddc9f7c9c887b6154bcb123b1984358e51..9b752fadaa3d1b292e36702c933ffbcf08897bf5 100644 (file)
@@ -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);
 }
 
index 544c2d0b280856494d8019b48cedde17eae0b73a..fbe4e02ca68a551728e57169c641d48e8eedd0b2 100644 (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);
index 6979083f1948690d5f468b2ce45d2c43be5d82f8..0496a864e4dd4c028a07ab7bf4f52c353471c02e 100644 (file)
--- 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;
 }
 
 /*
index 3d405bc408140423b7561dfd67585f29741676b0..8818d0232e4c5a517e3cdb3388ae9dff9d3648ab 100644 (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;
 }