diff --git a/toxcore/onion.c b/toxcore/onion.c index 7cfc8ecc..7d0c53e3 100644 --- a/toxcore/onion.c +++ b/toxcore/onion.c @@ -22,6 +22,12 @@ #include "onion.h" +#define MAX_ONION_SIZE 1400 + +#define RETURN_1 (crypto_secretbox_NONCEBYTES + sizeof(IP_Port) + crypto_secretbox_MACBYTES) +#define RETURN_2 (crypto_secretbox_NONCEBYTES + sizeof(IP_Port) + crypto_secretbox_MACBYTES + RETURN_1) +#define RETURN_3 (crypto_secretbox_NONCEBYTES + sizeof(IP_Port) + crypto_secretbox_MACBYTES + RETURN_2) + static int handle_send_initial(void *object, IP_Port source, uint8_t *packet, uint32_t length) { Onion *onion = object; @@ -48,6 +54,31 @@ static int handle_recv_3(void *object, IP_Port source, uint8_t *packet, uint32_t { Onion *onion = object; + if (length > MAX_ONION_SIZE) + return 1; + + if (length <= 1 + RETURN_3) + return 1; + + uint8_t plain[sizeof(IP_Port) + RETURN_2]; + int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_secretbox_NONCEBYTES, + sizeof(IP_Port) + RETURN_2 + crypto_secretbox_MACBYTES, plain); + + if ((uint32_t)len != sizeof(plain)) + return 1; + + IP_Port send_to; + memcpy(&send_to, plain, sizeof(IP_Port)); + + uint8_t data[MAX_ONION_SIZE]; + data[0] = NET_PACKET_ONION_RECV_2; + memcpy(data + 1, plain + sizeof(IP_Port), RETURN_2); + memcpy(data + 1 + RETURN_2, packet + 1 + RETURN_3, length - (1 + RETURN_3)); + uint32_t data_len = 1 + RETURN_2 + (length - (1 + RETURN_3)); + + if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len) + return 1; + return 0; } @@ -55,6 +86,31 @@ static int handle_recv_2(void *object, IP_Port source, uint8_t *packet, uint32_t { Onion *onion = object; + if (length > MAX_ONION_SIZE) + return 1; + + if (length <= 1 + RETURN_2) + return 1; + + uint8_t plain[sizeof(IP_Port) + RETURN_1]; + int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_secretbox_NONCEBYTES, + sizeof(IP_Port) + RETURN_1 + crypto_secretbox_MACBYTES, plain); + + if ((uint32_t)len != sizeof(plain)) + return 1; + + IP_Port send_to; + memcpy(&send_to, plain, sizeof(IP_Port)); + + uint8_t data[MAX_ONION_SIZE]; + data[0] = NET_PACKET_ONION_RECV_1; + memcpy(data + 1, plain + sizeof(IP_Port), RETURN_1); + memcpy(data + 1 + RETURN_1, packet + 1 + RETURN_2, length - (1 + RETURN_2)); + uint32_t data_len = 1 + RETURN_1 + (length - (1 + RETURN_2)); + + if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len) + return 1; + return 0; } @@ -62,11 +118,29 @@ static int handle_recv_1(void *object, IP_Port source, uint8_t *packet, uint32_t { Onion *onion = object; + if (length > MAX_ONION_SIZE) + return 1; + + if (length <= 1 + RETURN_1) + return 1; + + IP_Port send_to; + + int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_secretbox_NONCEBYTES, + sizeof(IP_Port) + crypto_secretbox_MACBYTES, (uint8_t *) &send_to); + + if ((uint32_t)len != sizeof(IP_Port)) + return 1; + + uint32_t data_len = length - (1 + RETURN_1); + + if ((uint32_t)sendpacket(onion->net, send_to, packet + (1 + RETURN_1), data_len) != data_len) + return 1; + return 0; } - Onion *new_onion(DHT *dht) { if (dht == NULL) @@ -77,28 +151,30 @@ Onion *new_onion(DHT *dht) if (onion == NULL) return NULL; + onion->dht = dht; + onion->net = dht->c->lossless_udp->net; new_symmetric_key(onion->secret_symmetric_key); - networking_registerhandler(dht->c->lossless_udp->net, NET_PACKET_ONION_SEND_INITIAL, &handle_send_initial, onion); - networking_registerhandler(dht->c->lossless_udp->net, NET_PACKET_ONION_SEND_1, &handle_send_1, onion); - networking_registerhandler(dht->c->lossless_udp->net, NET_PACKET_ONION_SEND_1, &handle_send_2, onion); + networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_INITIAL, &handle_send_initial, onion); + networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_1, &handle_send_1, onion); + networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_1, &handle_send_2, onion); + + networking_registerhandler(onion->net, NET_PACKET_ONION_RECV_3, &handle_recv_3, onion); + networking_registerhandler(onion->net, NET_PACKET_ONION_RECV_2, &handle_recv_2, onion); + networking_registerhandler(onion->net, NET_PACKET_ONION_RECV_1, &handle_recv_1, onion); - networking_registerhandler(dht->c->lossless_udp->net, NET_PACKET_ONION_RECV_3, &handle_recv_3, onion); - networking_registerhandler(dht->c->lossless_udp->net, NET_PACKET_ONION_RECV_2, &handle_recv_2, onion); - networking_registerhandler(dht->c->lossless_udp->net, NET_PACKET_ONION_RECV_1, &handle_recv_1, onion); - return onion; } void kill_onion(Onion *onion) { - networking_registerhandler(onion->dht->c->lossless_udp->net, NET_PACKET_ONION_SEND_INITIAL, NULL, NULL); - networking_registerhandler(onion->dht->c->lossless_udp->net, NET_PACKET_ONION_SEND_1, NULL, NULL); - networking_registerhandler(onion->dht->c->lossless_udp->net, NET_PACKET_ONION_SEND_1, NULL, NULL); + networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_INITIAL, NULL, NULL); + networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_1, NULL, NULL); + networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_1, NULL, NULL); - networking_registerhandler(onion->dht->c->lossless_udp->net, NET_PACKET_ONION_RECV_3, NULL, NULL); - networking_registerhandler(onion->dht->c->lossless_udp->net, NET_PACKET_ONION_RECV_2, NULL, NULL); - networking_registerhandler(onion->dht->c->lossless_udp->net, NET_PACKET_ONION_RECV_1, NULL, NULL); + networking_registerhandler(onion->net, NET_PACKET_ONION_RECV_3, NULL, NULL); + networking_registerhandler(onion->net, NET_PACKET_ONION_RECV_2, NULL, NULL); + networking_registerhandler(onion->net, NET_PACKET_ONION_RECV_1, NULL, NULL); free(onion); } diff --git a/toxcore/onion.h b/toxcore/onion.h index fd14c417..97ac3021 100644 --- a/toxcore/onion.h +++ b/toxcore/onion.h @@ -24,6 +24,7 @@ typedef struct { DHT *dht; + Networking_Core *net; uint8_t secret_symmetric_key[crypto_secretbox_KEYBYTES]; } Onion;