Make datagram SPTPS key exchange more robust.

Similar to old style key exchange requests, keep track of whether a key
exchange is already in progress and how long it took. If no key is known yet
or if key exchange takes too long, (re)start a new key exchange.
This commit is contained in:
Guus Sliepen 2012-10-07 13:31:19 +02:00
parent b99af2f813
commit bb6b97ce34
4 changed files with 47 additions and 29 deletions

View file

@ -234,6 +234,10 @@ static void check_reachability(void) {
/* TODO: only clear status.validkey if node is unreachable? */
n->status.validkey = false;
if(n->status.sptps) {
sptps_stop(&n->sptps);
n->status.waitingforkey = false;
}
n->last_req_key = 0;
n->maxmtu = MTU;

View file

@ -389,39 +389,48 @@ void receive_tcppacket(connection_t *c, const char *buffer, int len) {
}
static void send_sptps_packet(node_t *n, vpn_packet_t *origpkt) {
if(n->status.sptps) {
uint8_t type = 0;
int offset = 0;
if(!(origpkt->data[12] | origpkt->data[13])) {
sptps_send_record(&n->sptps, PKT_PROBE, (char *)origpkt->data, origpkt->len);
return;
if(!n->status.validkey) {
logger(DEBUG_TRAFFIC, LOG_INFO, "No valid key known yet for %s (%s)", n->name, n->hostname);
if(!n->status.waitingforkey)
send_req_key(n);
else if(n->last_req_key + 10 < time(NULL)) {
sptps_stop(&n->sptps);
n->status.waitingforkey = false;
send_req_key(n);
}
}
if(routing_mode == RMODE_ROUTER)
offset = 14;
else
type = PKT_MAC;
uint8_t type = 0;
int offset = 0;
if(origpkt->len < offset)
return;
vpn_packet_t outpkt;
if(n->outcompression) {
int len = compress_packet(outpkt.data + offset, origpkt->data + offset, origpkt->len - offset, n->outcompression);
if(len < 0) {
logger(DEBUG_TRAFFIC, LOG_ERR, "Error while compressing packet to %s (%s)", n->name, n->hostname);
} else if(len < origpkt->len - offset) {
outpkt.len = len + offset;
origpkt = &outpkt;
type |= PKT_COMPRESSED;
}
}
sptps_send_record(&n->sptps, type, (char *)origpkt->data + offset, origpkt->len - offset);
if(!(origpkt->data[12] | origpkt->data[13])) {
sptps_send_record(&n->sptps, PKT_PROBE, (char *)origpkt->data, origpkt->len);
return;
}
if(routing_mode == RMODE_ROUTER)
offset = 14;
else
type = PKT_MAC;
if(origpkt->len < offset)
return;
vpn_packet_t outpkt;
if(n->outcompression) {
int len = compress_packet(outpkt.data + offset, origpkt->data + offset, origpkt->len - offset, n->outcompression);
if(len < 0) {
logger(DEBUG_TRAFFIC, LOG_ERR, "Error while compressing packet to %s (%s)", n->name, n->hostname);
} else if(len < origpkt->len - offset) {
outpkt.len = len + offset;
origpkt = &outpkt;
type |= PKT_COMPRESSED;
}
}
sptps_send_record(&n->sptps, type, (char *)origpkt->data + offset, origpkt->len - offset);
return;
}
static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
@ -620,6 +629,7 @@ bool receive_sptps_record(void *handle, uint8_t type, const char *data, uint16_t
if(type == SPTPS_HANDSHAKE) {
from->status.validkey = true;
from->status.waitingforkey = false;
logger(DEBUG_META, LOG_INFO, "SPTPS key exchange with %s (%s) succesful", from->name, from->hostname);
return true;
}

View file

@ -30,7 +30,7 @@
typedef struct node_status_t {
unsigned int unused_active:1; /* 1 if active (not used for nodes) */
unsigned int validkey:1; /* 1 if we currently have a valid key for him */
unsigned int unused_waitingforkey:1; /* 1 if we already sent out a request */
unsigned int waitingforkey:1; /* 1 if we already sent out a request */
unsigned int visited:1; /* 1 if this node has been visited by one of the graph algorithms */
unsigned int reachable:1; /* 1 if this node is reachable in the graph */
unsigned int indirect:1; /* 1 if this node is not directly reachable by us */

View file

@ -116,6 +116,8 @@ bool send_req_key(node_t *to) {
snprintf(label, sizeof label, "tinc UDP key expansion %s %s", myself->name, to->name);
sptps_stop(&to->sptps);
to->status.validkey = false;
to->status.waitingforkey = true;
to->last_req_key = time(NULL);
to->incompression = myself->incompression;
return sptps_start(&to->sptps, to, true, true, myself->connection->ecdsa, to->ecdsa, label, sizeof label, send_initial_sptps_data, receive_sptps_record);
}
@ -172,6 +174,8 @@ static bool req_key_ext_h(connection_t *c, const char *request, node_t *from, in
snprintf(label, sizeof label, "tinc UDP key expansion %s %s", from->name, myself->name);
sptps_stop(&from->sptps);
from->status.validkey = false;
from->status.waitingforkey = true;
from->last_req_key = time(NULL);
sptps_start(&from->sptps, from, false, true, myself->connection->ecdsa, from->ecdsa, label, sizeof label, send_sptps_data, receive_sptps_record);
sptps_receive_data(&from->sptps, buf, len);
return true;