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");
}
*/
uint8_t sb_data[ONION_ANNOUNCE_SENDBACK_DATA_LENGTH];
static int handled_test_3;
uint8_t test_3_pub_key[crypto_box_PUBLICKEYBYTES];
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;
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;
uint8_t plain[ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_hash_sha256_BYTES];
//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);
ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_hash_sha256_BYTES + crypto_box_MACBYTES, plain);
if (len == -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));
handled_test_3 = 1;
return 0;
@ -157,9 +164,10 @@ START_TEST(test_basic)
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};
randombytes(sb_data, sizeof(sb_data));
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);
zeroes, onion1->dht->c->self_public_key, sb_data);
ck_assert_msg(ret == 0, "Failed to create/send onion announce_request packet.");
handled_test_3 = 0;
@ -168,11 +176,12 @@ START_TEST(test_basic)
do_onion(onion2);
}
randombytes(sb_data, sizeof(sb_data));
memcpy(onion2_a->entries[1].public_key, onion2->dht->self_public_key, crypto_box_PUBLICKEYBYTES);
onion2_a->entries[1].time = unix_time();
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,
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,
crypto_box_PUBLICKEYBYTES) != 0) {

View File

@ -97,7 +97,7 @@ Data sent to Node D:
announce request packet:
[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 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:
announce response packet:
[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)
data to route response packet:

View File

@ -27,12 +27,11 @@
#include "LAN_discovery.h"
#include "util.h"
#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)
#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_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 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.
* 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.
* 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 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 *client_id, uint8_t *sendback_data)
{
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 plain[ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH];
memcpy(plain, ping_id, ONION_PING_ID_SIZE);
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];
packet[0] = NET_PACKET_ANNOUNCE_REQUEST;
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)
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,
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))
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);
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);
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,
packet + (ANNOUNCE_REQUEST_SIZE_RECV - ONION_RETURN_3));
} 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*/
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);
uint8_t nonce[crypto_box_NONCEBYTES];
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) {
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];
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;
data[0] = NET_PACKET_ANNOUNCE_RESPONSE;

View File

@ -27,6 +27,9 @@
#define ONION_ANNOUNCE_MAX_ENTRIES 32
#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 {
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.
* 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.
* 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 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 *client_id, uint8_t *sendback_data);
/* Create and send an onion data request packet.
*