Tests added and some fixes for the onion part.

This commit is contained in:
irungentoo 2014-01-05 19:22:38 -05:00
parent 7e2d21271a
commit 6cd1e7fb70
6 changed files with 166 additions and 24 deletions

View File

@ -12,6 +12,13 @@
#include "../toxcore/onion.h" #include "../toxcore/onion.h"
#include "../toxcore/onion_announce.h" #include "../toxcore/onion_announce.h"
#ifdef __WIN32__
#define c_sleep(x) Sleep(1*x)
#else
#include <unistd.h>
#define c_sleep(x) usleep(1000*x)
#endif
void do_onion(Onion *onion) void do_onion(Onion *onion)
{ {
networking_poll(onion->net); 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; handled_test_2 = 1;
return 0; 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) START_TEST(test_basic)
{ {
@ -72,7 +111,7 @@ START_TEST(test_basic)
nodes[1] = n2; nodes[1] = n2;
nodes[2] = n1; nodes[2] = n1;
nodes[3] = n2; 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."); ck_assert_msg(ret == 0, "Failed to create/send onion packet.");
handled_test_1 = 0; handled_test_1 = 0;
@ -89,13 +128,69 @@ START_TEST(test_basic)
do_onion(onion1); do_onion(onion1);
do_onion(onion2); 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 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) 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 END_TEST

View File

@ -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) 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; struct sockaddr_storage addr;
#ifdef WIN32 #ifdef WIN32
int addrlen = sizeof(addr); int addrlen = sizeof(addr);

View File

@ -44,7 +44,7 @@
* return -1 on failure. * return -1 on failure.
* return 0 on success. * 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) if (1 + length + SEND_1 > MAX_ONION_SIZE || length == 0)
return -1; 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]; uint8_t packet[1 + length + SEND_1];
packet[0] = NET_PACKET_ONION_SEND_INITIAL; packet[0] = NET_PACKET_ONION_SEND_INITIAL;
memcpy(packet + 1, nonce, crypto_box_NONCEBYTES); 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); 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) if ((uint32_t)len != sizeof(IP_Port) + SEND_BASE * 2 + length + crypto_box_MACBYTES)
return -1; 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 -1;
return 0; return 0;

View File

@ -49,7 +49,7 @@ typedef struct {
* return -1 on failure. * return -1 on failure.
* return 0 on success. * 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. /* Create and send a onion response sent initially to dest with.
* *

View File

@ -30,22 +30,57 @@
#define PING_ID_SIZE crypto_hash_sha256_BYTES #define PING_ID_SIZE crypto_hash_sha256_BYTES
#define PING_ID_TIMEOUT 10 #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_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 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) #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 */ /* 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) uint8_t *ping_id)
{ {
time /= PING_ID_TIMEOUT; 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, onion_a->secret_bytes, crypto_secretbox_KEYBYTES);
memcpy(data + crypto_secretbox_KEYBYTES, &time, sizeof(time)); 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), 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)); 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; Onion_Announce *onion_a = object;
if (length != ANNOUNCE_REQUEST_SIZE) if (length != ANNOUNCE_REQUEST_SIZE_RECV)
return 1; return 1;
uint8_t plain[PING_ID_SIZE + crypto_box_PUBLICKEYBYTES]; 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; return 1;
uint8_t ping_id1[PING_ID_SIZE]; uint8_t ping_id1[PING_ID_SIZE];
generate_ping_id(onion_a, unix_time(), packet + 1 + crypto_box_NONCEBYTES, generate_ping_id(onion_a, unix_time(), packet + 1 + crypto_box_NONCEBYTES, source, ping_id1);
packet + (ANNOUNCE_REQUEST_SIZE - ONION_RETURN_3), ping_id1);
uint8_t ping_id2[PING_ID_SIZE]; uint8_t ping_id2[PING_ID_SIZE];
generate_ping_id(onion_a, unix_time() + PING_ID_TIMEOUT, packet + 1 + crypto_box_NONCEBYTES, generate_ping_id(onion_a, unix_time() + PING_ID_TIMEOUT, packet + 1 + crypto_box_NONCEBYTES, source, ping_id2);
packet + (ANNOUNCE_REQUEST_SIZE - ONION_RETURN_3), ping_id2);
int stored = 0; int stored = 0;
if (memcmp(ping_id1, plain, PING_ID_SIZE) == 0 || memcmp(ping_id2, plain, PING_ID_SIZE) == 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, 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 { } else {
stored = (in_entries(onion_a, plain + PING_ID_SIZE) != -1); 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); memcpy(data + 1, nonce, crypto_box_NONCEBYTES);
if (send_onion_response(onion_a->net, source, data, 1 + crypto_box_NONCEBYTES + len, 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 1;
return 0; return 0;

View File

@ -29,10 +29,10 @@
#define ONION_ANNOUNCE_TIMEOUT 300 #define ONION_ANNOUNCE_TIMEOUT 300
typedef struct { typedef struct {
uint8_t public_key[crypto_box_PUBLICKEYBYTES]; uint8_t public_key[crypto_box_PUBLICKEYBYTES];
IP_Port ret_ip_port; IP_Port ret_ip_port;
uint8_t ret[ONION_RETURN_3]; uint8_t ret[ONION_RETURN_3];
uint64_t time; uint64_t time;
} Onion_Announce_Entry; } Onion_Announce_Entry;
typedef struct { typedef struct {
@ -43,7 +43,20 @@ typedef struct {
uint8_t secret_bytes[crypto_secretbox_KEYBYTES]; uint8_t secret_bytes[crypto_secretbox_KEYBYTES];
} Onion_Announce; } 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); Onion_Announce *new_onion_announce(DHT *dht);