X-Git-Url: https://tinc-vpn.org/git/browse?a=blobdiff_plain;f=src%2Fnet_packet.c;h=fc24c9a545a6ba72bd5ec0fe505b55580e368ea9;hb=3ccdf50beb6b2d3f2730bdc66006b43190537cde;hp=1fdc0fe807b9b767d7d8e6fc8c8514eff6ce333b;hpb=7e6b2dd1ea51057b7135139c200d97a9e8f9c9cb;p=tinc diff --git a/src/net_packet.c b/src/net_packet.c index 1fdc0fe8..fc24c9a5 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -260,7 +260,7 @@ static bool try_mac(node_t *n, const vpn_packet_t *inpkt) { if(!n->status.validkey_in || !digest_active(n->indigest) || inpkt->len < sizeof(seqno_t) + digest_length(n->indigest)) return false; - return digest_verify(n->indigest, SEQNO(inpkt), inpkt->len - digest_length(n->indigest), DATA(inpkt) + inpkt->len - digest_length(n->indigest)); + return digest_verify(n->indigest, inpkt->data, inpkt->len - digest_length(n->indigest), inpkt->data + inpkt->len - digest_length(n->indigest)); #endif } @@ -282,13 +282,19 @@ static bool receive_udppacket(node_t *n, vpn_packet_t *inpkt) { } return false; } - inpkt->offset += 2 * sizeof(node_id_t); n->status.udppacket = true; - bool result = sptps_receive_data(&n->sptps, DATA(inpkt), inpkt->len - 2 * sizeof(node_id_t)); + bool result = sptps_receive_data(&n->sptps, DATA(inpkt), inpkt->len); n->status.udppacket = false; if(!result) { - logger(DEBUG_TRAFFIC, LOG_ERR, "Got bad packet from %s (%s)", n->name, n->hostname); + /* Uh-oh. It might be that the tunnel is stuck in some corrupted state, + so let's restart SPTPS in case that helps. But don't do that too often + to prevent storms, and because that would make life a little too easy + for external attackers trying to DoS us. */ + if(n->last_req_key < now.tv_sec - 10) { + logger(DEBUG_PROTOCOL, LOG_ERR, "Failed to decode raw TCP packet from %s (%s), restarting SPTPS", n->name, n->hostname); + send_req_key(n); + } return false; } return true; @@ -464,11 +470,17 @@ bool receive_tcppacket_sptps(connection_t *c, const char *data, int len) { /* The packet is for us */ - if(!from->status.validkey) { - logger(DEBUG_PROTOCOL, LOG_ERR, "Got SPTPS packet from %s (%s) but we don't have a valid key yet", from->name, from->hostname); + if(!sptps_receive_data(&from->sptps, data, len)) { + /* Uh-oh. It might be that the tunnel is stuck in some corrupted state, + so let's restart SPTPS in case that helps. But don't do that too often + to prevent storms. */ + if(from->last_req_key < now.tv_sec - 10) { + logger(DEBUG_PROTOCOL, LOG_ERR, "Failed to decode raw TCP packet from %s (%s), restarting SPTPS", from->name, from->hostname); + send_req_key(from); + } return true; } - sptps_receive_data(&from->sptps, data, len); + send_mtu_info(myself, from, MTU); return true; } @@ -735,7 +747,7 @@ bool send_sptps_data(node_t *to, node_t *from, int type, const void *data, size_ /* Send it via TCP if it is a handshake packet, TCPOnly is in use, this is a relay packet that the other node cannot understand, or this packet is larger than the MTU. */ if(type == SPTPS_HANDSHAKE || tcponly || (!direct && !relay_supported) || (type != PKT_PROBE && (len - SPTPS_DATAGRAM_OVERHEAD) > relay->minmtu)) { - if((from != myself || to->status.validkey) && (to->nexthop->connection->options >> 24) >= 7) { + if(type != SPTPS_HANDSHAKE && (to->nexthop->connection->options >> 24) >= 7) { char buf[len + sizeof to->id + sizeof from->id]; char* buf_ptr = buf; memcpy(buf_ptr, &to->id, sizeof to->id); buf_ptr += sizeof to->id; memcpy(buf_ptr, &from->id, sizeof from->id); buf_ptr += sizeof from->id; @@ -746,9 +758,10 @@ bool send_sptps_data(node_t *to, node_t *from, int type, const void *data, size_ char buf[len * 4 / 3 + 5]; b64encode(data, buf, len); - /* If no valid key is known yet, send the packets using ANS_KEY requests, - to ensure we get to learn the reflexive UDP address. */ - if(from == myself && !to->status.validkey) { + /* If this is a handshake packet, use ANS_KEY instead of REQ_KEY, for two reasons: + - We don't want intermediate nodes to switch to UDP to relay these packets; + - ANS_KEY allows us to learn the reflexive UDP address. */ + if(type == SPTPS_HANDSHAKE) { to->incompression = myself->incompression; return send_request(to->nexthop->connection, "%d %s %s %s -1 -1 -1 %d", ANS_KEY, from->name, to->name, buf, to->incompression); } else { @@ -1177,15 +1190,13 @@ static void try_tx_sptps(node_t *n, bool mtu) { node_t *via = (n->via == myself) ? n->nexthop : n->via; - /* If the static relay doesn't support SPTPS, everything goes via TCP anyway. */ + /* If we do have a static relay, try everything with that one instead, if it supports relaying. */ - if((via->options >> 24) < 4) - return; - - /* If we do have a static relay, try everything with that one instead. */ - - if(via != n) + if(via != n) { + if((via->options >> 24) < 4) + return; return try_tx_sptps(via, mtu); + } /* Otherwise, try to establish UDP connectivity. */ @@ -1336,7 +1347,7 @@ static node_t *try_harder(const sockaddr_t *from, const vpn_packet_t *pkt) { if(!n->status.reachable || n == myself) continue; - if((n->status.sptps && !n->sptps.instate) || !n->status.validkey_in) + if(!n->status.validkey_in && !(n->status.sptps && n->sptps.instate)) continue; bool soft = false; @@ -1426,10 +1437,16 @@ skip_harder: return; } + pkt.offset = 0; + if(n->status.sptps) { - pkt.offset = 2 * sizeof(node_id_t); + bool relay_enabled = (n->options >> 24) >= 4; + if (relay_enabled) { + pkt.offset = 2 * sizeof(node_id_t); + pkt.len -= pkt.offset; + } - if(!memcmp(DSTID(&pkt), &nullid, sizeof nullid)) { + if(!memcmp(DSTID(&pkt), &nullid, sizeof nullid) || !relay_enabled) { direct = true; from = n; to = myself; @@ -1454,7 +1471,7 @@ skip_harder: /* If we're not the final recipient, relay the packet. */ if(to != myself) { - send_sptps_data(to, from, 0, DATA(&pkt), pkt.len - 2 * sizeof(node_id_t)); + send_sptps_data(to, from, 0, DATA(&pkt), pkt.len); try_tx_sptps(to, true); return; } @@ -1463,7 +1480,6 @@ skip_harder: from = n; } - pkt.offset = 0; if(!receive_udppacket(from, &pkt)) return;