From 6cd1e7fb707e20681e066b0a7e452e15c227c280 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sun, 5 Jan 2014 19:22:38 -0500 Subject: [PATCH] Tests added and some fixes for the onion part. --- auto_tests/onion_test.c | 101 +++++++++++++++++++++++++++++++++++++-- toxcore/network.c | 1 + toxcore/onion.c | 8 ++-- toxcore/onion.h | 2 +- toxcore/onion_announce.c | 55 ++++++++++++++++----- toxcore/onion_announce.h | 23 +++++++-- 6 files changed, 166 insertions(+), 24 deletions(-) diff --git a/auto_tests/onion_test.c b/auto_tests/onion_test.c index 684b7a4f..57ac71d8 100644 --- a/auto_tests/onion_test.c +++ b/auto_tests/onion_test.c @@ -12,6 +12,13 @@ #include "../toxcore/onion.h" #include "../toxcore/onion_announce.h" +#ifdef __WIN32__ +#define c_sleep(x) Sleep(1*x) +#else +#include +#define c_sleep(x) usleep(1000*x) +#endif + void do_onion(Onion *onion) { networking_poll(onion->net); @@ -46,6 +53,38 @@ static int handle_test_2(void *object, IP_Port source, uint8_t *packet, uint32_t handled_test_2 = 1; return 0; } +/* +void print_client_id(uint8_t *client_id, uint32_t length) +{ + uint32_t j; + + for (j = 0; j < length; j++) { + printf("%02hhX", client_id[j]); + } + printf("\n"); +} +*/ +static int handled_test_3; +uint8_t test_3_pub_key[crypto_box_PUBLICKEYBYTES]; +uint8_t test_3_ping_id[crypto_hash_sha256_BYTES]; +static int handle_test_3(void *object, IP_Port source, uint8_t *packet, uint32_t length) +{ + Onion *onion = object; + + if (length != (1 + crypto_box_NONCEBYTES + crypto_hash_sha256_BYTES + crypto_box_MACBYTES)) + return 1; + + //print_client_id(packet, length); + int len = decrypt_data(test_3_pub_key, onion->dht->c->self_secret_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES, + crypto_hash_sha256_BYTES + crypto_box_MACBYTES, test_3_ping_id); + + if (len == -1) + return 1; + + //print_client_id(test_3_ping_id, sizeof(test_3_ping_id)); + handled_test_3 = 1; + return 0; +} START_TEST(test_basic) { @@ -72,7 +111,7 @@ START_TEST(test_basic) nodes[1] = n2; nodes[2] = n1; nodes[3] = n2; - int ret = send_onion_packet(onion1, nodes, (uint8_t *)"Install Gentoo", sizeof("Install Gentoo")); + int ret = send_onion_packet(onion1->dht, nodes, (uint8_t *)"Install Gentoo", sizeof("Install Gentoo")); ck_assert_msg(ret == 0, "Failed to create/send onion packet."); handled_test_1 = 0; @@ -89,13 +128,69 @@ START_TEST(test_basic) do_onion(onion1); do_onion(onion2); } + + Onion_Announce *onion1_a = new_onion_announce(onion1->dht); + Onion_Announce *onion2_a = new_onion_announce(onion2->dht); + networking_registerhandler(onion1->net, NET_PACKET_ANNOUNCE_RESPONSE, &handle_test_3, onion1); + ck_assert_msg((onion1_a != NULL) && (onion2_a != NULL), "Onion_Announce failed initializing."); + uint8_t zeroes[64] = {0}; + memcpy(test_3_pub_key, nodes[3].client_id, crypto_box_PUBLICKEYBYTES); + ret = send_announce_request(onion1->dht, nodes, onion1->dht->c->self_public_key, onion1->dht->c->self_secret_key, + zeroes, onion1->dht->c->self_public_key); + ck_assert_msg(ret == 0, "Failed to create/send onion announce_request packet."); + handled_test_3 = 0; + + while (handled_test_3 == 0) { + do_onion(onion1); + do_onion(onion2); + } + + send_announce_request(onion1->dht, nodes, onion1->dht->c->self_public_key, onion1->dht->c->self_secret_key, + test_3_ping_id, onion1->dht->c->self_public_key); + + while (memcmp(onion2_a->entries[ONION_ANNOUNCE_MAX_ENTRIES - 1].public_key, onion1->dht->c->self_public_key, + crypto_box_PUBLICKEYBYTES) != 0) { + do_onion(onion1); + do_onion(onion2); + c_sleep(50); + } } END_TEST +typedef struct { + Onion *onion; + Onion_Announce *onion_a; +} Onions; + +Onions *new_onions(uint16_t port) +{ + IP ip; + ip_init(&ip, 1); + ip.ip6.uint8[15] = 1; + Onions *on = malloc(sizeof(Onions)); + DHT *dht = new_DHT(new_net_crypto(new_networking(ip, port))); + on->onion = new_onion(dht); + on->onion_a = new_onion_announce(dht); + + if (on->onion && on->onion_a) + return on; + + return NULL; +} + +#define NUM_ONIONS 64 + START_TEST(test_announce) { - - + uint32_t i; + Onions *onions[NUM_ONIONS]; + + for (i = 0; i < NUM_ONIONS; ++i) { + onions[i] = new_onions(i + 34655); + ck_assert_msg(onions[i] != 0, "Failed to create onions. %u"); + } + + } END_TEST diff --git a/toxcore/network.c b/toxcore/network.c index 35f7c51d..b534db9c 100644 --- a/toxcore/network.c +++ b/toxcore/network.c @@ -226,6 +226,7 @@ int sendpacket(Networking_Core *net, IP_Port ip_port, uint8_t *data, uint32_t le */ static int receivepacket(sock_t sock, IP_Port *ip_port, uint8_t *data, uint32_t *length) { + memset(ip_port, 0, sizeof(IP_Port)); struct sockaddr_storage addr; #ifdef WIN32 int addrlen = sizeof(addr); diff --git a/toxcore/onion.c b/toxcore/onion.c index 17443fe0..7ec6bb61 100644 --- a/toxcore/onion.c +++ b/toxcore/onion.c @@ -44,7 +44,7 @@ * return -1 on failure. * return 0 on success. */ -int send_onion_packet(Onion *onion, Node_format *nodes, uint8_t *data, uint32_t length) +int send_onion_packet(DHT *dht, Node_format *nodes, uint8_t *data, uint32_t length) { if (1 + length + SEND_1 > MAX_ONION_SIZE || length == 0) return -1; @@ -82,15 +82,15 @@ int send_onion_packet(Onion *onion, Node_format *nodes, uint8_t *data, uint32_t uint8_t packet[1 + length + SEND_1]; packet[0] = NET_PACKET_ONION_SEND_INITIAL; memcpy(packet + 1, nonce, crypto_box_NONCEBYTES); - memcpy(packet + 1 + crypto_box_NONCEBYTES, onion->dht->self_public_key, crypto_box_PUBLICKEYBYTES); + memcpy(packet + 1 + crypto_box_NONCEBYTES, dht->self_public_key, crypto_box_PUBLICKEYBYTES); - len = encrypt_data(nodes[0].client_id, onion->dht->self_secret_key, nonce, + len = encrypt_data(nodes[0].client_id, dht->self_secret_key, nonce, step3, sizeof(step3), packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES); if ((uint32_t)len != sizeof(IP_Port) + SEND_BASE * 2 + length + crypto_box_MACBYTES) return -1; - if ((uint32_t)sendpacket(onion->net, nodes[0].ip_port, packet, sizeof(packet)) != sizeof(packet)) + if ((uint32_t)sendpacket(dht->c->lossless_udp->net, nodes[0].ip_port, packet, sizeof(packet)) != sizeof(packet)) return -1; return 0; diff --git a/toxcore/onion.h b/toxcore/onion.h index bb4687fe..b46dbdfe 100644 --- a/toxcore/onion.h +++ b/toxcore/onion.h @@ -49,7 +49,7 @@ typedef struct { * return -1 on failure. * return 0 on success. */ -int send_onion_packet(Onion *onion, Node_format *nodes, uint8_t *data, uint32_t length); +int send_onion_packet(DHT *dht, Node_format *nodes, uint8_t *data, uint32_t length); /* Create and send a onion response sent initially to dest with. * diff --git a/toxcore/onion_announce.c b/toxcore/onion_announce.c index 891c308e..8c314b18 100644 --- a/toxcore/onion_announce.c +++ b/toxcore/onion_announce.c @@ -30,22 +30,57 @@ #define PING_ID_SIZE crypto_hash_sha256_BYTES #define PING_ID_TIMEOUT 10 -#define ANNOUNCE_REQUEST_SIZE (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES + ONION_RETURN_3) +#define ANNOUNCE_REQUEST_SIZE (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES) +#define ANNOUNCE_REQUEST_SIZE_RECV (ANNOUNCE_REQUEST_SIZE + ONION_RETURN_3) #define ANNOUNCE_RESPONSE_MIN_SIZE (1 + crypto_box_NONCEBYTES + PING_ID_SIZE + crypto_box_MACBYTES) #define ANNOUNCE_RESPONSE_MAX_SIZE (ANNOUNCE_RESPONSE_MIN_SIZE + sizeof(Node_format)*MAX_SENT_NODES) #define DATA_REQUEST_MIN_SIZE (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES + ONION_RETURN_3) +/* Create and send an onion announce request packet. + * + * nodes is a list of 4 nodes, the packet will route through nodes 0, 1, 2 and the data + * with length length will arrive at 3. + * + * public_key and secret_key is the kepair which will be used to encrypt the request. + * ping_id is the ping id that will be sent in the request. + * client_id is the client id of the node we are searching for. + * + * return -1 on failure. + * return 0 on success. + */ +int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *secret_key, uint8_t *ping_id, + uint8_t *client_id) +{ + uint8_t plain[PING_ID_SIZE + crypto_box_PUBLICKEYBYTES]; + memcpy(plain, ping_id, PING_ID_SIZE); + memcpy(plain + PING_ID_SIZE, client_id, crypto_box_PUBLICKEYBYTES); + + uint8_t packet[ANNOUNCE_REQUEST_SIZE]; + packet[0] = NET_PACKET_ANNOUNCE_REQUEST; + new_nonce(packet + 1); + + int len = encrypt_data(nodes[3].client_id, secret_key, packet + 1, plain, sizeof(plain), + packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES); + + if ((uint32_t)len + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES != ANNOUNCE_REQUEST_SIZE) + return -1; + + memcpy(packet + 1 + crypto_box_NONCEBYTES, public_key, crypto_box_PUBLICKEYBYTES); + + return send_onion_packet(dht, nodes, packet, sizeof(packet)); +} + /* Generate a ping_id and put it in ping_id */ -static void generate_ping_id(Onion_Announce *onion_a, uint64_t time, uint8_t *public_key, uint8_t *ret, +static void generate_ping_id(Onion_Announce *onion_a, uint64_t time, uint8_t *public_key, IP_Port ret_ip_port, uint8_t *ping_id) { time /= PING_ID_TIMEOUT; - uint8_t data[crypto_secretbox_KEYBYTES + sizeof(time) + crypto_box_PUBLICKEYBYTES + ONION_RETURN_3]; + uint8_t data[crypto_secretbox_KEYBYTES + sizeof(time) + crypto_box_PUBLICKEYBYTES + sizeof(ret_ip_port)]; memcpy(data, onion_a->secret_bytes, crypto_secretbox_KEYBYTES); memcpy(data + crypto_secretbox_KEYBYTES, &time, sizeof(time)); memcpy(data + crypto_secretbox_KEYBYTES + sizeof(time), public_key, crypto_box_PUBLICKEYBYTES); - memcpy(data + crypto_secretbox_KEYBYTES + sizeof(time) + crypto_box_PUBLICKEYBYTES, ret, ONION_RETURN_3); + memcpy(data + crypto_secretbox_KEYBYTES + sizeof(time) + crypto_box_PUBLICKEYBYTES, &ret_ip_port, sizeof(ret_ip_port)); crypto_hash_sha256(ping_id, data, sizeof(data)); } @@ -138,7 +173,7 @@ static int handle_announce_request(void *object, IP_Port source, uint8_t *packet { Onion_Announce *onion_a = object; - if (length != ANNOUNCE_REQUEST_SIZE) + if (length != ANNOUNCE_REQUEST_SIZE_RECV) return 1; uint8_t plain[PING_ID_SIZE + crypto_box_PUBLICKEYBYTES]; @@ -150,18 +185,16 @@ static int handle_announce_request(void *object, IP_Port source, uint8_t *packet return 1; uint8_t ping_id1[PING_ID_SIZE]; - generate_ping_id(onion_a, unix_time(), packet + 1 + crypto_box_NONCEBYTES, - packet + (ANNOUNCE_REQUEST_SIZE - ONION_RETURN_3), ping_id1); + generate_ping_id(onion_a, unix_time(), packet + 1 + crypto_box_NONCEBYTES, source, ping_id1); uint8_t ping_id2[PING_ID_SIZE]; - generate_ping_id(onion_a, unix_time() + PING_ID_TIMEOUT, packet + 1 + crypto_box_NONCEBYTES, - packet + (ANNOUNCE_REQUEST_SIZE - ONION_RETURN_3), ping_id2); + generate_ping_id(onion_a, unix_time() + PING_ID_TIMEOUT, packet + 1 + crypto_box_NONCEBYTES, source, ping_id2); int stored = 0; if (memcmp(ping_id1, plain, PING_ID_SIZE) == 0 || memcmp(ping_id2, plain, PING_ID_SIZE) == 0) { stored = add_to_entries(onion_a, source, packet + 1 + crypto_box_NONCEBYTES, - packet + (ANNOUNCE_REQUEST_SIZE - ONION_RETURN_3)); + packet + (ANNOUNCE_REQUEST_SIZE_RECV - ONION_RETURN_3)); } else { stored = (in_entries(onion_a, plain + PING_ID_SIZE) != -1); } @@ -193,7 +226,7 @@ static int handle_announce_request(void *object, IP_Port source, uint8_t *packet memcpy(data + 1, nonce, crypto_box_NONCEBYTES); if (send_onion_response(onion_a->net, source, data, 1 + crypto_box_NONCEBYTES + len, - packet + (ANNOUNCE_REQUEST_SIZE - ONION_RETURN_3)) == -1) + packet + (ANNOUNCE_REQUEST_SIZE_RECV - ONION_RETURN_3)) == -1) return 1; return 0; diff --git a/toxcore/onion_announce.h b/toxcore/onion_announce.h index c8d9b442..66a8702d 100644 --- a/toxcore/onion_announce.h +++ b/toxcore/onion_announce.h @@ -29,10 +29,10 @@ #define ONION_ANNOUNCE_TIMEOUT 300 typedef struct { - uint8_t public_key[crypto_box_PUBLICKEYBYTES]; - IP_Port ret_ip_port; - uint8_t ret[ONION_RETURN_3]; - uint64_t time; + uint8_t public_key[crypto_box_PUBLICKEYBYTES]; + IP_Port ret_ip_port; + uint8_t ret[ONION_RETURN_3]; + uint64_t time; } Onion_Announce_Entry; typedef struct { @@ -43,7 +43,20 @@ typedef struct { uint8_t secret_bytes[crypto_secretbox_KEYBYTES]; } Onion_Announce; - +/* Create and send an onion announce request packet. + * + * nodes is a list of 4 nodes, the packet will route through nodes 0, 1, 2 and the data + * with length length will arrive at 3. + * + * public_key and secret_key is the kepair which will be used to encrypt the request. + * ping_id is the ping id that will be sent in the request. + * client_id is the client id of the node we are searching for. + * + * return -1 on failure. + * return 0 on success. + */ +int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *secret_key, uint8_t *ping_id, + uint8_t *client_id); Onion_Announce *new_onion_announce(DHT *dht);