Fixed problem in onion_announce.c

Added a way to know if a announce response is valid.
This commit is contained in:
irungentoo 2014-01-08 20:15:35 -05:00
parent 5e6e503201
commit 0fd8e49c38
4 changed files with 46 additions and 27 deletions

View File

@ -65,6 +65,7 @@ void print_client_id(uint8_t *client_id, uint32_t length)
printf("\n"); printf("\n");
} }
*/ */
uint8_t sb_data[ONION_ANNOUNCE_SENDBACK_DATA_LENGTH];
static int handled_test_3; static int handled_test_3;
uint8_t test_3_pub_key[crypto_box_PUBLICKEYBYTES]; uint8_t test_3_pub_key[crypto_box_PUBLICKEYBYTES];
uint8_t test_3_ping_id[crypto_hash_sha256_BYTES]; uint8_t test_3_ping_id[crypto_hash_sha256_BYTES];
@ -72,16 +73,22 @@ static int handle_test_3(void *object, IP_Port source, uint8_t *packet, uint32_t
{ {
Onion *onion = object; Onion *onion = object;
if (length != (1 + crypto_box_NONCEBYTES + crypto_hash_sha256_BYTES + crypto_box_MACBYTES)) if (length != (1 + crypto_box_NONCEBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_hash_sha256_BYTES +
crypto_box_MACBYTES))
return 1; return 1;
uint8_t plain[ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_hash_sha256_BYTES];
//print_client_id(packet, length); //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, 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); ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_hash_sha256_BYTES + crypto_box_MACBYTES, plain);
if (len == -1) if (len == -1)
return 1; return 1;
if (memcmp(plain, sb_data, ONION_ANNOUNCE_SENDBACK_DATA_LENGTH) != 0)
return 1;
memcpy(test_3_ping_id, plain + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH, crypto_hash_sha256_BYTES);
//print_client_id(test_3_ping_id, sizeof(test_3_ping_id)); //print_client_id(test_3_ping_id, sizeof(test_3_ping_id));
handled_test_3 = 1; handled_test_3 = 1;
return 0; return 0;
@ -157,9 +164,10 @@ START_TEST(test_basic)
networking_registerhandler(onion1->net, NET_PACKET_ANNOUNCE_RESPONSE, &handle_test_3, onion1); 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."); ck_assert_msg((onion1_a != NULL) && (onion2_a != NULL), "Onion_Announce failed initializing.");
uint8_t zeroes[64] = {0}; uint8_t zeroes[64] = {0};
randombytes(sb_data, sizeof(sb_data));
memcpy(test_3_pub_key, nodes[3].client_id, crypto_box_PUBLICKEYBYTES); 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, 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); zeroes, onion1->dht->c->self_public_key, sb_data);
ck_assert_msg(ret == 0, "Failed to create/send onion announce_request packet."); ck_assert_msg(ret == 0, "Failed to create/send onion announce_request packet.");
handled_test_3 = 0; handled_test_3 = 0;
@ -168,11 +176,12 @@ START_TEST(test_basic)
do_onion(onion2); do_onion(onion2);
} }
randombytes(sb_data, sizeof(sb_data));
memcpy(onion2_a->entries[1].public_key, onion2->dht->self_public_key, crypto_box_PUBLICKEYBYTES); memcpy(onion2_a->entries[1].public_key, onion2->dht->self_public_key, crypto_box_PUBLICKEYBYTES);
onion2_a->entries[1].time = unix_time(); onion2_a->entries[1].time = unix_time();
networking_registerhandler(onion1->net, NET_PACKET_ONION_DATA_RESPONSE, &handle_test_4, onion1); networking_registerhandler(onion1->net, NET_PACKET_ONION_DATA_RESPONSE, &handle_test_4, onion1);
send_announce_request(onion1->dht, nodes, onion1->dht->c->self_public_key, onion1->dht->c->self_secret_key, 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); test_3_ping_id, onion1->dht->c->self_public_key, sb_data);
while (memcmp(onion2_a->entries[ONION_ANNOUNCE_MAX_ENTRIES - 2].public_key, onion1->dht->c->self_public_key, while (memcmp(onion2_a->entries[ONION_ANNOUNCE_MAX_ENTRIES - 2].public_key, onion1->dht->c->self_public_key,
crypto_box_PUBLICKEYBYTES) != 0) { crypto_box_PUBLICKEYBYTES) != 0) {

View File

@ -97,7 +97,7 @@ Data sent to Node D:
announce request packet: announce request packet:
[uint8_t packet id (131)][nonce][our real long term public key or a temporary one (see next)] [uint8_t packet id (131)][nonce][our real long term public key or a temporary one (see next)]
encrypted (with our real long term private key if we want to announce ourselves, a temporary one if we are searching for friends) and the pub key of Node D and the nonce:[[(32 bytes) ping_id][client id we are searching for]] encrypted (with our real long term private key if we want to announce ourselves, a temporary one if we are searching for friends) and the pub key of Node D and the nonce:[[(32 bytes) ping_id][client id we are searching for][data to send back in response(fixed size)]]
(if the ping id is zero, respond with a announce response packet) (if the ping id is zero, respond with a announce response packet)
(If the ping id matches the one the node sent in the announce response and the public key matches the one being searched for, (If the ping id matches the one the node sent in the announce response and the public key matches the one being searched for,
@ -111,7 +111,7 @@ encrypted with that temporary private key and the nonce and the real public key
Data sent to us: Data sent to us:
announce response packet: announce response packet:
[uint8_t packet id (132)][nonce] [uint8_t packet id (132)][nonce]
encrypted with the DHT private key of Node D, the public key in the request and the nonce:[[(32 bytes) ping_id][Node_Format * (maximum of 8)]] encrypted with the DHT private key of Node D, the public key in the request and the nonce:[[data to send back in response(fixed size)][(32 bytes) ping_id][Node_Format * (maximum of 8)]]
(if the ping id is zero, it means the information to reach the client id we are searching for is stored on this node) (if the ping id is zero, it means the information to reach the client id we are searching for is stored on this node)
data to route response packet: data to route response packet:

View File

@ -27,12 +27,11 @@
#include "LAN_discovery.h" #include "LAN_discovery.h"
#include "util.h" #include "util.h"
#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) #define ANNOUNCE_REQUEST_SIZE (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_MACBYTES)
#define ANNOUNCE_REQUEST_SIZE_RECV (ANNOUNCE_REQUEST_SIZE + ONION_RETURN_3) #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 + ONION_PING_ID_SIZE + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + 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) #define DATA_REQUEST_MIN_SIZE (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES)
@ -46,17 +45,19 @@
* public_key and secret_key is the kepair which will be used to encrypt the request. * 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. * 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. * client_id is the client id of the node we are searching for.
* sendback_data is the data of ONION_ANNOUNCE_SENDBACK_DATA_LENGTH length that we expect to
* receive back in the response.
* *
* return -1 on failure. * return -1 on failure.
* return 0 on success. * 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, 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 *client_id, uint8_t *sendback_data)
{ {
uint8_t plain[PING_ID_SIZE + crypto_box_PUBLICKEYBYTES]; uint8_t plain[ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH];
memcpy(plain, ping_id, PING_ID_SIZE); memcpy(plain, ping_id, ONION_PING_ID_SIZE);
memcpy(plain + PING_ID_SIZE, client_id, crypto_box_PUBLICKEYBYTES); memcpy(plain + ONION_PING_ID_SIZE, client_id, crypto_box_PUBLICKEYBYTES);
memcpy(plain + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES, sendback_data, ONION_ANNOUNCE_SENDBACK_DATA_LENGTH);
uint8_t packet[ANNOUNCE_REQUEST_SIZE]; uint8_t packet[ANNOUNCE_REQUEST_SIZE];
packet[0] = NET_PACKET_ANNOUNCE_REQUEST; packet[0] = NET_PACKET_ANNOUNCE_REQUEST;
new_nonce(packet + 1); new_nonce(packet + 1);
@ -210,50 +211,54 @@ static int handle_announce_request(void *object, IP_Port source, uint8_t *packet
if (length != ANNOUNCE_REQUEST_SIZE_RECV) if (length != ANNOUNCE_REQUEST_SIZE_RECV)
return 1; return 1;
uint8_t plain[PING_ID_SIZE + crypto_box_PUBLICKEYBYTES]; uint8_t plain[ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH];
int len = decrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion_a->dht->self_secret_key, packet + 1, int len = decrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion_a->dht->self_secret_key, packet + 1,
packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES,
PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES, plain); ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_MACBYTES, plain);
if ((uint32_t)len != sizeof(plain)) if ((uint32_t)len != sizeof(plain))
return 1; return 1;
uint8_t ping_id1[PING_ID_SIZE]; uint8_t ping_id1[ONION_PING_ID_SIZE];
generate_ping_id(onion_a, unix_time(), packet + 1 + crypto_box_NONCEBYTES, source, ping_id1); generate_ping_id(onion_a, unix_time(), packet + 1 + crypto_box_NONCEBYTES, source, ping_id1);
uint8_t ping_id2[PING_ID_SIZE]; uint8_t ping_id2[ONION_PING_ID_SIZE];
generate_ping_id(onion_a, unix_time() + PING_ID_TIMEOUT, packet + 1 + crypto_box_NONCEBYTES, source, ping_id2); generate_ping_id(onion_a, unix_time() + PING_ID_TIMEOUT, packet + 1 + crypto_box_NONCEBYTES, source, 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, ONION_PING_ID_SIZE) == 0 || memcmp(ping_id2, plain, ONION_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_RECV - 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 + ONION_PING_ID_SIZE) != -1);
} }
/*Respond with a announce response packet*/ /*Respond with a announce response packet*/
Node_format nodes_list[MAX_SENT_NODES]; Node_format nodes_list[MAX_SENT_NODES];
uint32_t num_nodes = get_close_nodes(onion_a->dht, plain + PING_ID_SIZE, nodes_list, source.ip.family, uint32_t num_nodes = get_close_nodes(onion_a->dht, plain + ONION_PING_ID_SIZE, nodes_list, source.ip.family,
LAN_ip(source.ip) == 0, 1); LAN_ip(source.ip) == 0, 1);
uint8_t nonce[crypto_box_NONCEBYTES]; uint8_t nonce[crypto_box_NONCEBYTES];
new_nonce(nonce); new_nonce(nonce);
uint8_t pl[PING_ID_SIZE + sizeof(nodes_list)] = {0}; uint8_t pl[ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + ONION_PING_ID_SIZE + sizeof(nodes_list)] = {0};
memcpy(pl, plain + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES, ONION_ANNOUNCE_SENDBACK_DATA_LENGTH);
if (!stored) { if (!stored) {
memcpy(pl, ping_id2, PING_ID_SIZE); memcpy(pl + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH, ping_id2, ONION_PING_ID_SIZE);
} }
memcpy(pl + PING_ID_SIZE, nodes_list, num_nodes * sizeof(Node_format)); memcpy(pl + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + ONION_PING_ID_SIZE, nodes_list, num_nodes * sizeof(Node_format));
uint8_t data[ANNOUNCE_RESPONSE_MAX_SIZE]; uint8_t data[ANNOUNCE_RESPONSE_MAX_SIZE];
len = encrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion_a->dht->self_secret_key, nonce, pl, len = encrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion_a->dht->self_secret_key, nonce, pl,
PING_ID_SIZE + num_nodes * sizeof(Node_format), data + 1 + crypto_box_NONCEBYTES); ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + ONION_PING_ID_SIZE + num_nodes * sizeof(Node_format),
data + 1 + crypto_box_NONCEBYTES);
if ((uint32_t)len != PING_ID_SIZE + num_nodes * sizeof(Node_format) + crypto_box_MACBYTES) if ((uint32_t)len != ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + ONION_PING_ID_SIZE + num_nodes * sizeof(
Node_format) + crypto_box_MACBYTES)
return 1; return 1;
data[0] = NET_PACKET_ANNOUNCE_RESPONSE; data[0] = NET_PACKET_ANNOUNCE_RESPONSE;

View File

@ -27,6 +27,9 @@
#define ONION_ANNOUNCE_MAX_ENTRIES 32 #define ONION_ANNOUNCE_MAX_ENTRIES 32
#define ONION_ANNOUNCE_TIMEOUT 300 #define ONION_ANNOUNCE_TIMEOUT 300
#define ONION_PING_ID_SIZE crypto_hash_sha256_BYTES
#define ONION_ANNOUNCE_SENDBACK_DATA_LENGTH (crypto_secretbox_NONCEBYTES + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES + crypto_secretbox_MACBYTES)
typedef struct { typedef struct {
uint8_t public_key[crypto_box_PUBLICKEYBYTES]; uint8_t public_key[crypto_box_PUBLICKEYBYTES];
@ -51,12 +54,14 @@ typedef struct {
* public_key and secret_key is the kepair which will be used to encrypt the request. * 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. * 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. * client_id is the client id of the node we are searching for.
* sendback_data is the data of ONION_ANNOUNCE_SENDBACK_DATA_LENGTH length that we expect to
* receive back in the response.
* *
* return -1 on failure. * return -1 on failure.
* return 0 on success. * 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, 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 *client_id, uint8_t *sendback_data);
/* Create and send an onion data request packet. /* Create and send an onion data request packet.
* *