Onion data packets can now be handled in onion_client.

oniondata_registerhandler(...) can be used to register different packet
types to handle them and send_onion_data(...) can be used to send these
packets.
This commit is contained in:
irungentoo 2014-01-14 14:20:42 -05:00
parent 878762a8e4
commit a49a09f94b
6 changed files with 120 additions and 11 deletions

View File

@ -96,6 +96,7 @@ static int handle_test_3(void *object, IP_Port source, uint8_t *packet, uint32_t
return 0;
}
uint8_t nonce[crypto_box_NONCEBYTES];
static int handled_test_4;
static int handle_test_4(void *object, IP_Port source, uint8_t *packet, uint32_t length)
{
@ -105,6 +106,10 @@ static int handle_test_4(void *object, IP_Port source, uint8_t *packet, uint32_t
return 1;
uint8_t plain[sizeof("Install gentoo")] = {0};
if (memcmp(nonce, packet + 1, crypto_box_NONCEBYTES) != 0)
return 1;
int len = decrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion->dht->c->self_secret_key, packet + 1,
packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, sizeof("Install gentoo") + crypto_box_MACBYTES, plain);
@ -195,7 +200,9 @@ START_TEST(test_basic)
c_sleep(1000);
Onion *onion3 = new_onion(new_DHT(new_net_crypto(new_networking(ip, 34569))));
ck_assert_msg((onion3 != NULL), "Onion failed initializing.");
ret = send_data_request(onion3->dht, nodes, onion1->dht->c->self_public_key, (uint8_t *)"Install gentoo",
new_nonce(nonce);
ret = send_data_request(onion3->dht, nodes, onion1->dht->c->self_public_key, nonce, (uint8_t *)"Install gentoo",
sizeof("Install gentoo"));
ck_assert_msg(ret == 0, "Failed to create/send onion data_request packet.");
handled_test_4 = 0;

View File

@ -108,6 +108,9 @@ data to route request packet:
encrypted with that temporary private key and the nonce and the real public key of the destination node:[data]
(if Node D contains the ret data for the node, it sends the stuff in this packet as a data to route response packet to the right node)
The data in the previous packet is in format: [real public key of sender]
encrypted with real private key of the sender, the nonce in the data packet and the real public key of the reciever:[[uint8_t id][data (optional)]]
Data sent to us:
announce response packet:
[uint8_t packet id (132)][data to send back in response(fixed size)][nonce]
@ -117,6 +120,8 @@ encrypted with the DHT private key of Node D, the public key in the request and
data to route response packet:
[uint8_t packet id (134)][nonce][temporary just generated public key]
encrypted with that temporary private key and the nonce and the real public key of the destination node:[data]
Onion packet (response):
initial (sent from node D to node C):

View File

@ -78,16 +78,17 @@ int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uin
* send the packet to that person in the form of a response)
*
* public_key is the real public key of the node which we want to send the data of length length to.
* nonce is the nonce to encrypt this packet with
*
* return -1 on failure.
* return 0 on success.
*/
int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *data, uint16_t length)
int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *nonce, uint8_t *data, uint16_t length)
{
uint8_t packet[DATA_REQUEST_MIN_SIZE + length];
packet[0] = NET_PACKET_ONION_DATA_REQUEST;
memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES);
new_nonce(packet + 1 + crypto_box_PUBLICKEYBYTES);
memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES);
uint8_t random_public_key[crypto_box_PUBLICKEYBYTES];
uint8_t random_secret_key[crypto_box_SECRETKEYBYTES];

View File

@ -75,11 +75,13 @@ int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uin
* send the packet to that person in the form of a response)
*
* public_key is the real public key of the node which we want to send the data of length length to.
* nonce is the nonce to encrypt this packet with
*
* return -1 on failure.
* return 0 on success.
*/
int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *data, uint16_t length);
int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *nonce, uint8_t *data,
uint16_t length);
Onion_Announce *new_onion_announce(DHT *dht);

View File

@ -30,6 +30,7 @@
#define ANNOUNCE_TIMEOUT 10
uint8_t zero_ping[ONION_PING_ID_SIZE];
/* Creates a sendback for use in an announce request.
*
@ -297,26 +298,93 @@ static int handle_announce_response(void *object, IP_Port source, uint8_t *packe
return 0;
}
#define DATA_IN_RESPONSE_MIN_SIZE (crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES)
static int handle_data_response(void *object, IP_Port source, uint8_t *packet, uint32_t length)
{
Onion_Client *onion_c = object;
if (length <= ONION_DATA_RESPONSE_MIN_SIZE)
if (length <= (ONION_DATA_RESPONSE_MIN_SIZE + DATA_IN_RESPONSE_MIN_SIZE))
return 1;
if (length > MAX_DATA_SIZE)
return 1;
uint8_t plain[length - ONION_DATA_RESPONSE_MIN_SIZE];
uint8_t temp_plain[length - ONION_DATA_RESPONSE_MIN_SIZE];
int len = decrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion_c->dht->c->self_secret_key, packet + 1,
packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES,
length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES), plain);
length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES), temp_plain);
if ((uint32_t)len != sizeof(temp_plain))
return 1;
uint8_t plain[sizeof(temp_plain) - DATA_IN_RESPONSE_MIN_SIZE];
len = decrypt_data(temp_plain, onion_c->dht->c->self_secret_key, packet + 1, temp_plain + crypto_box_PUBLICKEYBYTES,
sizeof(temp_plain) - crypto_box_PUBLICKEYBYTES, plain);
if ((uint32_t)len != sizeof(plain))
return 1;
//TODO do something with the plain
return 0;
if (!onion_c->Onion_Data_Handlers[plain[0]].function)
return 1;
return onion_c->Onion_Data_Handlers[plain[0]].function(onion_c->Onion_Data_Handlers[plain[0]].object, temp_plain, plain,
sizeof(plain));
}
/* Send data of length length to friendnum.
* This data will be recieved by the friend using the Onion_Data_Handlers callbacks.
*
* Even if this function succeeds, the friend might not recieve any data.
*
* return the number of packets sent on success
* return -1 on failure.
*/
int send_onion_data(Onion_Client *onion_c, int friend_num, uint8_t *data, uint32_t length)
{
if ((uint32_t)friend_num >= onion_c->num_friends)
return -1;
if (length + DATA_IN_RESPONSE_MIN_SIZE + ONION_DATA_RESPONSE_MIN_SIZE + ONION_SEND_1 > MAX_DATA_SIZE)
return -1;
if (length == 0)
return -1;
uint8_t nonce[crypto_box_NONCEBYTES];
new_nonce(nonce);
uint8_t packet[DATA_IN_RESPONSE_MIN_SIZE + length];
memcpy(packet, onion_c->dht->c->self_public_key, crypto_box_PUBLICKEYBYTES);
int len = encrypt_data(onion_c->friends_list[friend_num].real_client_id, onion_c->dht->c->self_secret_key, nonce, data,
length, packet + crypto_box_PUBLICKEYBYTES);
if ((uint32_t)len + crypto_box_PUBLICKEYBYTES != sizeof(packet))
return -1;
uint32_t i, good = 0;
Onion_Node *list_nodes = onion_c->friends_list[friend_num].clients_list;
for (i = 0; i < MAX_ONION_CLIENTS; ++i) {
if (is_timeout(list_nodes[i].timestamp, ONION_NODE_TIMEOUT))
continue;
if (memcmp(list_nodes[i].ping_id, zero_ping, ONION_PING_ID_SIZE) == 0) {
Node_format nodes[4];
if (random_path(onion_c, nodes) == -1)
continue;
memcpy(nodes[3].client_id, list_nodes[i].client_id, crypto_box_PUBLICKEYBYTES);
nodes[3].ip_port = list_nodes[i].ip_port;
if (send_data_request(onion_c->dht, nodes, onion_c->friends_list[friend_num].real_client_id, nonce, packet,
sizeof(packet)) == 0)
++good;
}
}
return good;
}
/* Get the friend_num of a friend.
@ -382,7 +450,7 @@ int onion_addfriend(Onion_Client *onion_c, uint8_t *client_id)
}
}
if (index == ~0) {
if (index == (uint32_t)~0) {
if (realloc_onion_friends(onion_c, onion_c->num_friends + 1) == -1)
return -1;
@ -453,7 +521,7 @@ int random_path(Onion_Client *onion_c, Node_format *nodes)
}
#define ANNOUNCE_FRIEND 30
uint8_t zero_ping[ONION_PING_ID_SIZE];
static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
{
if (friendnum >= onion_c->num_friends)
@ -489,6 +557,12 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
//TODO send packets to friend telling them our fake DHT id.
}
/* Function to call when onion data packet with contents beginning with byte is received. */
void oniondata_registerhandler(Onion_Client *onion_c, uint8_t byte, oniondata_handler_callback cb, void *object)
{
onion_c->Onion_Data_Handlers[byte].function = cb;
onion_c->Onion_Data_Handlers[byte].object = object;
}
#define ANNOUNCE_INTERVAL_NOT_ANNOUNCED 10
#define ANNOUNCE_INTERVAL_ANNOUNCED 60

View File

@ -48,6 +48,8 @@ typedef struct {
uint8_t temp_secret_key[crypto_box_SECRETKEYBYTES];
} Onion_Friend;
typedef int (*oniondata_handler_callback)(void *object, uint8_t *source_pubkey, uint8_t *data, uint32_t len);
typedef struct {
DHT *dht;
Networking_Core *net;
@ -58,6 +60,11 @@ typedef struct {
uint8_t secret_symmetric_key[crypto_secretbox_KEYBYTES];
uint64_t last_run;
struct {
oniondata_handler_callback function;
void *object;
} Onion_Data_Handlers[256];
} Onion_Client;
/* Add a friend who we want to connect to.
@ -99,6 +106,19 @@ int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port);
*/
int random_path(Onion_Client *onion_c, Node_format *nodes);
/* Send data of length length to friendnum.
* This data will be recieved by the friend using the Onion_Data_Handlers callbacks.
*
* Even if this function succeeds, the friend might not recieve any data.
*
* return the number of packets sent on success
* return -1 on failure.
*/
int send_onion_data(Onion_Client *onion_c, int friend_num, uint8_t *data, uint32_t length);
/* Function to call when onion data packet with contents beginning with byte is received. */
void oniondata_registerhandler(Onion_Client *onion_c, uint8_t byte, oniondata_handler_callback cb, void *object);
void do_onion_client(Onion_Client *onion_c);
Onion_Client *new_onion_client(DHT *dht);