Be liberal in accepting KEY_CHANGED/REQ_KEY/ANS_KEY requests.
authorGuus Sliepen <guus@tinc-vpn.org>
Sat, 23 Jan 2010 17:48:01 +0000 (18:48 +0100)
committerGuus Sliepen <guus@tinc-vpn.org>
Sat, 23 Jan 2010 17:48:01 +0000 (18:48 +0100)
When we got a key request for or from a node we don't know, we disconnected the
node that forwarded us that request.  However, especially in TunnelServer mode,
disconnecting does not help. We now ignore such requests, but since there is no
way of telling the original sender that the request was dropped, we now retry
sending REQ_KEY requests when we don't get an ANS_KEY back.

src/graph.c
src/net_packet.c
src/node.h
src/protocol_key.c

index f5aff5bfd7a2511e71042162408e390a332d19ea..7288f74bf4ebc8b0c4293cb638e77e15ae081511 100644 (file)
@@ -251,7 +251,7 @@ void sssp_bfs(void) {
                        /* TODO: only clear status.validkey if node is unreachable? */
 
                        n->status.validkey = false;
                        /* TODO: only clear status.validkey if node is unreachable? */
 
                        n->status.validkey = false;
-                       n->status.waitingforkey = false;
+                       n->last_req_key = 0;
 
                        n->maxmtu = MTU;
                        n->minmtu = 0;
 
                        n->maxmtu = MTU;
                        n->minmtu = 0;
index e5011532629d818062464a244f43de84785f6f91..dcf8df61826c368ccf0a2b167b6b9418a966a740 100644 (file)
@@ -353,10 +353,10 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
                                   "No valid key known yet for %s (%s), forwarding via TCP",
                                   n->name, n->hostname);
 
                                   "No valid key known yet for %s (%s), forwarding via TCP",
                                   n->name, n->hostname);
 
-               if(!n->status.waitingforkey)
+               if(n->last_req_key + 10 < now) {
                        send_req_key(n);
                        send_req_key(n);
-
-               n->status.waitingforkey = true;
+                       n->last_req_key = now;
+               }
 
                send_tcppacket(n->nexthop->connection, origpkt);
 
 
                send_tcppacket(n->nexthop->connection, origpkt);
 
index a621a0a204023214ca0604ea07653c8d74439b62..2f68a1ef0e0dcfa3bd7130aaf1115dc6a63718a1 100644 (file)
@@ -30,7 +30,7 @@
 typedef struct node_status_t {
        int unused_active:1;                    /* 1 if active (not used for nodes) */
        int validkey:1;                         /* 1 if we currently have a valid key for him */
 typedef struct node_status_t {
        int unused_active:1;                    /* 1 if active (not used for nodes) */
        int validkey:1;                         /* 1 if we currently have a valid key for him */
-       int waitingforkey:1;                    /* 1 if we already sent out a request */
+       int unused_waitingforkey:1;             /* 1 if we already sent out a request */
        int visited:1;                          /* 1 if this node has been visited by one of the graph algorithms */
        int reachable:1;                        /* 1 if this node is reachable in the graph */
        int indirect:1;                         /* 1 if this node is not directly reachable by us */
        int visited:1;                          /* 1 if this node has been visited by one of the graph algorithms */
        int reachable:1;                        /* 1 if this node is reachable in the graph */
        int indirect:1;                         /* 1 if this node is not directly reachable by us */
@@ -45,6 +45,7 @@ typedef struct node_t {
        char *hostname;                         /* the hostname of its real ip */
 
        node_status_t status;
        char *hostname;                         /* the hostname of its real ip */
 
        node_status_t status;
+       time_t last_req_key;
 
        const EVP_CIPHER *incipher;             /* Cipher type for UDP packets received from him */
        char *inkey;                            /* Cipher key and iv */
 
        const EVP_CIPHER *incipher;             /* Cipher type for UDP packets received from him */
        char *inkey;                            /* Cipher key and iv */
index 92948aa4d2f5571e94dc50c3427968a1cad89669..ad393d38668a52d8b6feb261b10d22bc1b2d5531 100644 (file)
@@ -57,6 +57,11 @@ bool key_changed_h(connection_t *c) {
                return false;
        }
 
                return false;
        }
 
+       if(!check_id(name)) {
+               logger(LOG_ERR, "Got bad %s from %s (%s): %s", "KEY_CHANGED", c->name, c->hostname, "invalid name");
+               return false;
+       }
+
        if(seen_request(c->buffer))
                return true;
 
        if(seen_request(c->buffer))
                return true;
 
@@ -65,11 +70,11 @@ bool key_changed_h(connection_t *c) {
        if(!n) {
                logger(LOG_ERR, "Got %s from %s (%s) origin %s which does not exist",
                           "KEY_CHANGED", c->name, c->hostname, name);
        if(!n) {
                logger(LOG_ERR, "Got %s from %s (%s) origin %s which does not exist",
                           "KEY_CHANGED", c->name, c->hostname, name);
-               return false;
+               return true;
        }
 
        n->status.validkey = false;
        }
 
        n->status.validkey = false;
-       n->status.waitingforkey = false;
+       n->last_req_key = 0;
 
        /* Tell the others */
 
 
        /* Tell the others */
 
@@ -94,12 +99,17 @@ bool req_key_h(connection_t *c) {
                return false;
        }
 
                return false;
        }
 
+       if(!check_id(from_name) || !check_id(to_name)) {
+               logger(LOG_ERR, "Got bad %s from %s (%s): %s", "REQ_KEY", c->name, c->hostname, "invalid name");
+               return false;
+       }
+
        from = lookup_node(from_name);
 
        if(!from) {
                logger(LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list",
                           "REQ_KEY", c->name, c->hostname, from_name);
        from = lookup_node(from_name);
 
        if(!from) {
                logger(LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list",
                           "REQ_KEY", c->name, c->hostname, from_name);
-               return false;
+               return true;
        }
 
        to = lookup_node(to_name);
        }
 
        to = lookup_node(to_name);
@@ -107,7 +117,7 @@ bool req_key_h(connection_t *c) {
        if(!to) {
                logger(LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list",
                           "REQ_KEY", c->name, c->hostname, to_name);
        if(!to) {
                logger(LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list",
                           "REQ_KEY", c->name, c->hostname, to_name);
-               return false;
+               return true;
        }
 
        /* Check if this key request is for us */
        }
 
        /* Check if this key request is for us */
@@ -116,7 +126,7 @@ bool req_key_h(connection_t *c) {
                send_ans_key(from);
        } else {
                if(tunnelserver)
                send_ans_key(from);
        } else {
                if(tunnelserver)
-                       return false;
+                       return true;
 
                if(!to->status.reachable) {
                        logger(LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable",
 
                if(!to->status.reachable) {
                        logger(LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable",
@@ -180,12 +190,17 @@ bool ans_key_h(connection_t *c) {
                return false;
        }
 
                return false;
        }
 
+       if(!check_id(from_name) || !check_id(to_name)) {
+               logger(LOG_ERR, "Got bad %s from %s (%s): %s", "ANS_KEY", c->name, c->hostname, "invalid name");
+               return false;
+       }
+
        from = lookup_node(from_name);
 
        if(!from) {
                logger(LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list",
                           "ANS_KEY", c->name, c->hostname, from_name);
        from = lookup_node(from_name);
 
        if(!from) {
                logger(LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list",
                           "ANS_KEY", c->name, c->hostname, from_name);
-               return false;
+               return true;
        }
 
        to = lookup_node(to_name);
        }
 
        to = lookup_node(to_name);
@@ -193,14 +208,14 @@ bool ans_key_h(connection_t *c) {
        if(!to) {
                logger(LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list",
                           "ANS_KEY", c->name, c->hostname, to_name);
        if(!to) {
                logger(LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list",
                           "ANS_KEY", c->name, c->hostname, to_name);
-               return false;
+               return true;
        }
 
        /* Forward it if necessary */
 
        if(to != myself) {
                if(tunnelserver)
        }
 
        /* Forward it if necessary */
 
        if(to != myself) {
                if(tunnelserver)
-                       return false;
+                       return true;
 
                if(!to->status.reachable) {
                        logger(LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable",
 
                if(!to->status.reachable) {
                        logger(LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable",
@@ -218,7 +233,6 @@ bool ans_key_h(connection_t *c) {
        from->outkeylength = strlen(key) / 2;
        hex2bin(key, from->outkey, from->outkeylength);
 
        from->outkeylength = strlen(key) / 2;
        hex2bin(key, from->outkey, from->outkeylength);
 
-       from->status.waitingforkey = false;
        /* Check and lookup cipher and digest algorithms */
 
        if(cipher) {
        /* Check and lookup cipher and digest algorithms */
 
        if(cipher) {
@@ -227,13 +241,13 @@ bool ans_key_h(connection_t *c) {
                if(!from->outcipher) {
                        logger(LOG_ERR, "Node %s (%s) uses unknown cipher!", from->name,
                                   from->hostname);
                if(!from->outcipher) {
                        logger(LOG_ERR, "Node %s (%s) uses unknown cipher!", from->name,
                                   from->hostname);
-                       return false;
+                       return true;
                }
 
                if(from->outkeylength != from->outcipher->key_len + from->outcipher->iv_len) {
                        logger(LOG_ERR, "Node %s (%s) uses wrong keylength!", from->name,
                                   from->hostname);
                }
 
                if(from->outkeylength != from->outcipher->key_len + from->outcipher->iv_len) {
                        logger(LOG_ERR, "Node %s (%s) uses wrong keylength!", from->name,
                                   from->hostname);
-                       return false;
+                       return true;
                }
        } else {
                from->outcipher = NULL;
                }
        } else {
                from->outcipher = NULL;
@@ -247,13 +261,13 @@ bool ans_key_h(connection_t *c) {
                if(!from->outdigest) {
                        logger(LOG_ERR, "Node %s (%s) uses unknown digest!", from->name,
                                   from->hostname);
                if(!from->outdigest) {
                        logger(LOG_ERR, "Node %s (%s) uses unknown digest!", from->name,
                                   from->hostname);
-                       return false;
+                       return true;
                }
 
                if(from->outmaclength > from->outdigest->md_size || from->outmaclength < 0) {
                        logger(LOG_ERR, "Node %s (%s) uses bogus MAC length!",
                                   from->name, from->hostname);
                }
 
                if(from->outmaclength > from->outdigest->md_size || from->outmaclength < 0) {
                        logger(LOG_ERR, "Node %s (%s) uses bogus MAC length!",
                                   from->name, from->hostname);
-                       return false;
+                       return true;
                }
        } else {
                from->outdigest = NULL;
                }
        } else {
                from->outdigest = NULL;
@@ -261,7 +275,7 @@ bool ans_key_h(connection_t *c) {
 
        if(compression < 0 || compression > 11) {
                logger(LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname);
 
        if(compression < 0 || compression > 11) {
                logger(LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname);
-               return false;
+               return true;
        }
        
        from->outcompression = compression;
        }
        
        from->outcompression = compression;
@@ -270,7 +284,7 @@ bool ans_key_h(connection_t *c) {
                if(!EVP_EncryptInit_ex(&from->outctx, from->outcipher, NULL, (unsigned char *)from->outkey, (unsigned char *)from->outkey + from->outcipher->key_len)) {
                        logger(LOG_ERR, "Error during initialisation of key from %s (%s): %s",
                                        from->name, from->hostname, ERR_error_string(ERR_get_error(), NULL));
                if(!EVP_EncryptInit_ex(&from->outctx, from->outcipher, NULL, (unsigned char *)from->outkey, (unsigned char *)from->outkey + from->outcipher->key_len)) {
                        logger(LOG_ERR, "Error during initialisation of key from %s (%s): %s",
                                        from->name, from->hostname, ERR_error_string(ERR_get_error(), NULL));
-                       return false;
+                       return true;
                }
 
        from->status.validkey = true;
                }
 
        from->status.validkey = true;