From: Guus Sliepen Date: Sat, 23 Jan 2010 17:48:01 +0000 (+0100) Subject: Be liberal in accepting KEY_CHANGED/REQ_KEY/ANS_KEY requests. X-Git-Tag: release-1.0.12~6 X-Git-Url: https://tinc-vpn.org/git/browse?p=tinc;a=commitdiff_plain;h=d15099e0029578bfd24d6b464b941f4693280001;hp=469fa318bc817908af9a51e3a980ffc998fae6f2 Be liberal in accepting KEY_CHANGED/REQ_KEY/ANS_KEY requests. 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. --- diff --git a/src/graph.c b/src/graph.c index f5aff5bf..7288f74b 100644 --- a/src/graph.c +++ b/src/graph.c @@ -251,7 +251,7 @@ void sssp_bfs(void) { /* 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; diff --git a/src/net_packet.c b/src/net_packet.c index e5011532..dcf8df61 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -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); - if(!n->status.waitingforkey) + if(n->last_req_key + 10 < now) { send_req_key(n); - - n->status.waitingforkey = true; + n->last_req_key = now; + } send_tcppacket(n->nexthop->connection, origpkt); diff --git a/src/node.h b/src/node.h index a621a0a2..2f68a1ef 100644 --- a/src/node.h +++ b/src/node.h @@ -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 */ - 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 */ @@ -45,6 +45,7 @@ typedef struct node_t { 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 */ diff --git a/src/protocol_key.c b/src/protocol_key.c index 92948aa4..ad393d38 100644 --- a/src/protocol_key.c +++ b/src/protocol_key.c @@ -57,6 +57,11 @@ bool key_changed_h(connection_t *c) { 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; @@ -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); - return false; + return true; } n->status.validkey = false; - n->status.waitingforkey = false; + n->last_req_key = 0; /* Tell the others */ @@ -94,12 +99,17 @@ bool req_key_h(connection_t *c) { 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); - return false; + return true; } 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); - return false; + return true; } /* 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) - return false; + return true; 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; } + 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); - return false; + return true; } 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); - return false; + return true; } /* 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", @@ -218,7 +233,6 @@ bool ans_key_h(connection_t *c) { from->outkeylength = strlen(key) / 2; hex2bin(key, from->outkey, from->outkeylength); - from->status.waitingforkey = false; /* 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); - 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); - return false; + return true; } } 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); - 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); - return false; + return true; } } 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); - return false; + return true; } 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)); - return false; + return true; } from->status.validkey = true;