Some work done on onion_client

This commit is contained in:
irungentoo 2014-01-11 21:19:50 -05:00
parent 94b5e55189
commit dac7fe0338
4 changed files with 135 additions and 25 deletions

View File

@ -27,7 +27,7 @@
#include "LAN_discovery.h" #include "LAN_discovery.h"
#include "util.h" #include "util.h"
#define PING_ID_TIMEOUT 10 #define PING_ID_TIMEOUT 20
#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 (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)
@ -135,7 +135,7 @@ static int in_entries(Onion_Announce *onion_a, uint8_t *public_key)
return -1; return -1;
} }
uint8_t cmp_public_key[crypto_box_PUBLICKEYBYTES]; static uint8_t cmp_public_key[crypto_box_PUBLICKEYBYTES];
static int cmp_entry(const void *a, const void *b) static int cmp_entry(const void *a, const void *b)
{ {
Onion_Announce_Entry entry1, entry2; Onion_Announce_Entry entry1, entry2;
@ -237,13 +237,16 @@ static int handle_announce_request(void *object, IP_Port source, uint8_t *packet
uint32_t num_nodes = get_close_nodes(onion_a->dht, plain + ONION_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);
uint32_t i;
for (i = 0; i < num_nodes; ++i)
to_net_family(&nodes_list[i].ip_port.ip);
uint8_t nonce[crypto_box_NONCEBYTES]; uint8_t nonce[crypto_box_NONCEBYTES];
new_nonce(nonce); new_nonce(nonce);
uint8_t pl[ONION_PING_ID_SIZE + sizeof(nodes_list)] = {0}; uint8_t pl[ONION_PING_ID_SIZE + sizeof(nodes_list)] = {0};
if (!stored) { if (!stored) {
memcpy(pl, ping_id2, ONION_PING_ID_SIZE); memcpy(pl, ping_id2, ONION_PING_ID_SIZE);
} }

View File

@ -29,7 +29,7 @@
#define ONION_ANNOUNCE_TIMEOUT 300 #define ONION_ANNOUNCE_TIMEOUT 300
#define ONION_PING_ID_SIZE crypto_hash_sha256_BYTES #define ONION_PING_ID_SIZE crypto_hash_sha256_BYTES
#define ONION_ANNOUNCE_SENDBACK_DATA_LENGTH (crypto_secretbox_NONCEBYTES + sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES + crypto_secretbox_MACBYTES) #define ONION_ANNOUNCE_SENDBACK_DATA_LENGTH (crypto_secretbox_NONCEBYTES + sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port) + crypto_secretbox_MACBYTES)
#define ONION_ANNOUNCE_RESPONSE_MIN_SIZE (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES + ONION_PING_ID_SIZE + crypto_box_MACBYTES) #define ONION_ANNOUNCE_RESPONSE_MIN_SIZE (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES + ONION_PING_ID_SIZE + crypto_box_MACBYTES)
#define ONION_ANNOUNCE_RESPONSE_MAX_SIZE (ONION_ANNOUNCE_RESPONSE_MIN_SIZE + sizeof(Node_format)*MAX_SENT_NODES) #define ONION_ANNOUNCE_RESPONSE_MAX_SIZE (ONION_ANNOUNCE_RESPONSE_MIN_SIZE + sizeof(Node_format)*MAX_SENT_NODES)

View File

@ -26,15 +26,19 @@
#include "onion_client.h" #include "onion_client.h"
#include "util.h" #include "util.h"
#include "LAN_discovery.h"
#define ANNOUNCE_TIMEOUT 10 #define ANNOUNCE_TIMEOUT 10
/* Creates a sendback for use in an announce request. /* Creates a sendback for use in an announce request.
* *
* num is 0 if we used our secret public key for the announce * num is 0 if we used our secret public key for the announce
* num is 1 + friendnum if we use a temporary one. * num is 1 + friendnum if we use a temporary one.
* *
* Public key is the key we will be sending it to. * Public key is the key we will be sending it to.
* ip_port is the ip_port of the node we will be sending
* it to.
* *
* sendback must be at least ONION_ANNOUNCE_SENDBACK_DATA_LENGTH big * sendback must be at least ONION_ANNOUNCE_SENDBACK_DATA_LENGTH big
* *
@ -42,13 +46,15 @@
* return 0 on success * return 0 on success
* *
*/ */
static int new_sendback(Onion_Client *onion_c, uint32_t num, uint8_t *public_key, uint8_t *sendback) static int new_sendback(Onion_Client *onion_c, uint32_t num, uint8_t *public_key, IP_Port ip_port, uint8_t *sendback)
{ {
uint8_t plain[sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES]; uint8_t plain[sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port)];
uint64_t time = unix_time(); uint64_t time = unix_time();
new_nonce(sendback);
memcpy(plain, &num, sizeof(uint32_t)); memcpy(plain, &num, sizeof(uint32_t));
memcpy(plain + sizeof(uint32_t), &time, sizeof(uint64_t)); memcpy(plain + sizeof(uint32_t), &time, sizeof(uint64_t));
memcpy(plain + sizeof(uint32_t) + sizeof(uint64_t), public_key, crypto_box_PUBLICKEYBYTES); memcpy(plain + sizeof(uint32_t) + sizeof(uint64_t), public_key, crypto_box_PUBLICKEYBYTES);
memcpy(plain + sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES, &ip_port, sizeof(IP_Port));
int len = encrypt_data_symmetric(onion_c->secret_symmetric_key, sendback, plain, sizeof(plain), int len = encrypt_data_symmetric(onion_c->secret_symmetric_key, sendback, plain, sizeof(plain),
sendback + crypto_secretbox_NONCEBYTES); sendback + crypto_secretbox_NONCEBYTES);
@ -59,34 +65,37 @@ static int new_sendback(Onion_Client *onion_c, uint32_t num, uint8_t *public_key
return 0; return 0;
} }
/* Checks if the sendback is valid and returns the public key contained in it in returned_pubkey /* Checks if the sendback is valid and returns the public key contained in it in ret_pubkey and the
* ip contained in it in ret_ip_port
* *
* sendback is the sendback ONION_ANNOUNCE_SENDBACK_DATA_LENGTH big * sendback is the sendback ONION_ANNOUNCE_SENDBACK_DATA_LENGTH big
* returned_pubkey must be at least crypto_box_PUBLICKEYBYTES big * ret_pubkey must be at least crypto_box_PUBLICKEYBYTES big
* ret_ip_port must be at least 1 big
* *
* return ~0 on failure * return ~0 on failure
* return num (see new_sendback(...)) on success * return num (see new_sendback(...)) on success
*/ */
static uint32_t check_sendback(Onion_Client *onion_c, uint8_t *sendback, uint8_t *returned_pubkey) static uint32_t check_sendback(Onion_Client *onion_c, uint8_t *sendback, uint8_t *ret_pubkey, IP_Port *ret_ip_port)
{ {
uint8_t plain[sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES]; uint8_t plain[sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port)];
int len = decrypt_data_symmetric(onion_c->secret_symmetric_key, sendback, sendback + crypto_secretbox_NONCEBYTES, int len = decrypt_data_symmetric(onion_c->secret_symmetric_key, sendback, sendback + crypto_secretbox_NONCEBYTES,
ONION_ANNOUNCE_SENDBACK_DATA_LENGTH - crypto_secretbox_NONCEBYTES, plain); ONION_ANNOUNCE_SENDBACK_DATA_LENGTH - crypto_secretbox_NONCEBYTES, plain);
if ((uint32_t)len != sizeof(plain)) if ((uint32_t)len != sizeof(plain))
return -1; return ~0;
uint64_t timestamp; uint64_t timestamp;
memcpy(&timestamp, plain + sizeof(uint32_t), sizeof(uint64_t)); memcpy(&timestamp, plain + sizeof(uint32_t), sizeof(uint64_t));
uint64_t temp_time = unix_time(); uint64_t temp_time = unix_time();
if (timestamp + ANNOUNCE_TIMEOUT < temp_time || temp_time < timestamp) if (timestamp + ANNOUNCE_TIMEOUT < temp_time || temp_time < timestamp)
return -1; return ~0;
memcpy(returned_pubkey, plain + sizeof(uint32_t) + sizeof(uint64_t), crypto_box_PUBLICKEYBYTES); memcpy(ret_pubkey, plain + sizeof(uint32_t) + sizeof(uint64_t), crypto_box_PUBLICKEYBYTES);
memcpy(ret_ip_port, plain + sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES, sizeof(IP_Port));
uint32_t num; uint32_t num;
memcpy(&num, plain, sizeof(uint32_t)); memcpy(&num, plain, sizeof(uint32_t));
return plain[0]; return num;
} }
static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_Port dest, uint8_t *dest_pubkey, static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_Port dest, uint8_t *dest_pubkey,
@ -97,7 +106,7 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_
uint8_t sendback[ONION_ANNOUNCE_SENDBACK_DATA_LENGTH]; uint8_t sendback[ONION_ANNOUNCE_SENDBACK_DATA_LENGTH];
if (new_sendback(onion_c, 0, dest_pubkey, sendback) == -1) if (new_sendback(onion_c, 0, dest_pubkey, dest, sendback) == -1)
return -1; return -1;
uint8_t zero_ping_id[ONION_PING_ID_SIZE] = {0}; uint8_t zero_ping_id[ONION_PING_ID_SIZE] = {0};
@ -124,14 +133,84 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_
} }
} }
static int client_add_to_list(Onion_Client *onion_c, uint32_t num, uint8_t *public_key, IP_Port ip_port, static uint8_t cmp_public_key[crypto_box_PUBLICKEYBYTES];
uint8_t *ping_id) static int cmp_entry(const void *a, const void *b)
{ {
Onion_Node entry1, entry2;
memcpy(&entry1, a, sizeof(Onion_Node));
memcpy(&entry2, b, sizeof(Onion_Node));
int t1 = is_timeout(entry1.timestamp, ONION_NODE_TIMEOUT);
int t2 = is_timeout(entry2.timestamp, ONION_NODE_TIMEOUT);
if (t1 && t2)
return 0;
if (t1)
return -1;
if (t2)
return 1;
int close = id_closest(cmp_public_key, entry1.client_id, entry2.client_id);
if (close == 1)
return 1;
if (close == 2)
return -1;
return 0; return 0;
} }
static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, Node_format *nodes, uint16_t num_nodes) static int client_add_to_list(Onion_Client *onion_c, uint32_t num, uint8_t *public_key, IP_Port ip_port,
uint8_t *ping_id)
{
if (num > onion_c->num_friends)
return -1;
Onion_Node *list_nodes = NULL;
uint8_t *reference_id = NULL;
if (num == 0) {
list_nodes = onion_c->clients_announce_list;
reference_id = onion_c->dht->c->self_public_key;
} else {
list_nodes = onion_c->friends_list[num - 1].clients_list;
reference_id = onion_c->friends_list[num - 1].real_client_id;
}
memcpy(cmp_public_key, reference_id, crypto_box_PUBLICKEYBYTES);
qsort(list_nodes, MAX_ONION_CLIENTS, sizeof(Onion_Node), cmp_entry);
int index = -1;
if (is_timeout(list_nodes[0].timestamp, ONION_NODE_TIMEOUT)
|| id_closest(reference_id, list_nodes[0].client_id, public_key) == 2) {
index = 0;
}
uint32_t i;
for (i = 0; i < MAX_ONION_CLIENTS; ++i) {
if (memcmp(list_nodes[i].client_id, public_key, crypto_box_PUBLICKEYBYTES) == 0) {
index = i;
break;
}
}
if (index == -1)
return 0;
memcpy(list_nodes[index].client_id, public_key, CLIENT_ID_SIZE);
list_nodes[index].ip_port = ip_port;
memcpy(list_nodes[index].ping_id, ping_id, ONION_PING_ID_SIZE);
list_nodes[index].timestamp = unix_time();
list_nodes[index].last_pinged = 0;
return 0;
}
static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, Node_format *nodes, uint16_t num_nodes,
IP_Port source)
{ {
if (num > onion_c->num_friends) if (num > onion_c->num_friends)
return -1; return -1;
@ -151,8 +230,15 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, Node_format *n
} }
uint32_t i; uint32_t i;
int lan_ips_accepted = (LAN_ip(source.ip) == 0);
for (i = 0; i < num_nodes; ++i) { for (i = 0; i < num_nodes; ++i) {
to_host_family(&nodes[i].ip_port.ip);
if (!lan_ips_accepted)
if (LAN_ip(nodes[i].ip_port.ip) == 0)
continue;
if (is_timeout(list_nodes[0].timestamp, ONION_NODE_TIMEOUT) if (is_timeout(list_nodes[0].timestamp, ONION_NODE_TIMEOUT)
|| id_closest(reference_id, list_nodes[0].client_id, nodes[i].client_id) == 2) { || id_closest(reference_id, list_nodes[0].client_id, nodes[i].client_id) == 2) {
client_send_announce_request(onion_c, num, nodes[i].ip_port, nodes[i].client_id, NULL); client_send_announce_request(onion_c, num, nodes[i].ip_port, nodes[i].client_id, NULL);
@ -175,8 +261,8 @@ static int handle_announce_response(void *object, IP_Port source, uint8_t *packe
uint16_t num_nodes = (length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE) / sizeof(Node_format); uint16_t num_nodes = (length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE) / sizeof(Node_format);
uint8_t public_key[crypto_box_PUBLICKEYBYTES]; uint8_t public_key[crypto_box_PUBLICKEYBYTES];
IP_Port ip_port;
uint32_t num = check_sendback(onion_c, packet + 1, public_key); uint32_t num = check_sendback(onion_c, packet + 1, public_key, &ip_port);
if (num > onion_c->num_friends) if (num > onion_c->num_friends)
return 1; return 1;
@ -201,11 +287,11 @@ static int handle_announce_response(void *object, IP_Port source, uint8_t *packe
if ((uint32_t)len != sizeof(plain)) if ((uint32_t)len != sizeof(plain))
return 1; return 1;
//TODO
//if (client_add_to_list(onion_c, num, uint8_t *public_key, IP_Port ip_port, plain) == -1)
// return 1;
if (client_ping_nodes(onion_c, num, (Node_format *)plain + ONION_PING_ID_SIZE, num_nodes) == -1) if (client_add_to_list(onion_c, num, public_key, ip_port, plain) == -1)
return 1;
if (client_ping_nodes(onion_c, num, (Node_format *)plain + ONION_PING_ID_SIZE, num_nodes, source) == -1)
return 1; return 1;
return 0; return 0;
@ -232,18 +318,37 @@ int random_path(Onion_Client *onion_c, Node_format *nodes)
return -1; return -1;
} }
uint8_t zero_ping[ONION_PING_ID_SIZE];
static void do_friend(Onion_Client *onion_c, uint16_t friendnum) static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
{ {
} }
#define ANNOUNCE_INTERVAL_NOT_ANNOUNCED 10
#define ANNOUNCE_INTERVAL_ANNOUNCED 60
static void do_announce(Onion_Client *onion_c) static void do_announce(Onion_Client *onion_c)
{ {
uint32_t i; uint32_t i;
Onion_Node *list_nodes = onion_c->clients_announce_list;
for (i = 0; i < MAX_ONION_CLIENTS; ++i) { for (i = 0; i < MAX_ONION_CLIENTS; ++i) {
if (is_timeout(list_nodes[i].timestamp, ONION_NODE_TIMEOUT))
continue;
uint32_t interval = ANNOUNCE_INTERVAL_NOT_ANNOUNCED;
if (memcmp(list_nodes[i].ping_id, zero_ping, ONION_PING_ID_SIZE) == 0) {
interval = ANNOUNCE_INTERVAL_ANNOUNCED;
}
if (is_timeout(list_nodes[i].last_pinged, interval)) {
if (client_send_announce_request(onion_c, 0, list_nodes[i].ip_port, list_nodes[i].client_id,
list_nodes[i].ping_id) == 0) {
list_nodes[i].last_pinged = unix_time();
}
}
} }
} }

View File

@ -33,6 +33,8 @@ typedef struct {
IP_Port ip_port; IP_Port ip_port;
uint8_t ping_id[ONION_PING_ID_SIZE]; uint8_t ping_id[ONION_PING_ID_SIZE];
uint64_t timestamp; uint64_t timestamp;
uint64_t last_pinged;
} Onion_Node; } Onion_Node;
typedef struct { typedef struct {