diff --git a/auto_tests/onion_test.c b/auto_tests/onion_test.c index 17151398..4dae2136 100644 --- a/auto_tests/onion_test.c +++ b/auto_tests/onion_test.c @@ -73,15 +73,15 @@ static int handle_test_3(void *object, IP_Port source, uint8_t *packet, uint32_t { Onion *onion = object; - if (length != (1 + crypto_box_NONCEBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_hash_sha256_BYTES + + if (length != (1 + crypto_box_NONCEBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + 1 + crypto_hash_sha256_BYTES + crypto_box_MACBYTES)) return 1; - uint8_t plain[crypto_hash_sha256_BYTES]; + uint8_t plain[1 + 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 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH, packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES, - crypto_hash_sha256_BYTES + crypto_box_MACBYTES, plain); + 1 + crypto_hash_sha256_BYTES + crypto_box_MACBYTES, plain); if (len == -1) return 1; @@ -90,7 +90,7 @@ static int handle_test_3(void *object, IP_Port source, uint8_t *packet, uint32_t if (memcmp(packet + 1, sb_data, ONION_ANNOUNCE_SENDBACK_DATA_LENGTH) != 0) return 1; - memcpy(test_3_ping_id, plain, crypto_hash_sha256_BYTES); + memcpy(test_3_ping_id, plain + 1, crypto_hash_sha256_BYTES); //print_client_id(test_3_ping_id, sizeof(test_3_ping_id)); handled_test_3 = 1; return 0; @@ -174,7 +174,7 @@ START_TEST(test_basic) 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, sb_data); + zeroes, onion1->dht->c->self_public_key, 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; @@ -188,7 +188,7 @@ START_TEST(test_basic) 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, sb_data); + test_3_ping_id, onion1->dht->c->self_public_key, 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) { @@ -202,8 +202,8 @@ START_TEST(test_basic) ck_assert_msg((onion3 != NULL), "Onion failed initializing."); new_nonce(nonce); - ret = send_data_request(onion3->dht, nodes, onion1->dht->c->self_public_key, nonce, (uint8_t *)"Install gentoo", - sizeof("Install gentoo")); + ret = send_data_request(onion3->dht, nodes, onion1->dht->c->self_public_key, 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; diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c index 0f54ed7e..06e8e257 100644 --- a/auto_tests/tox_test.c +++ b/auto_tests/tox_test.c @@ -23,8 +23,9 @@ void accept_friend_request(uint8_t *public_key, uint8_t *data, uint16_t length, { Tox *t = userdata; - if (length == 7 && memcmp("Gentoo", data, 7) == 0) + if (length == 7 && memcmp("Gentoo", data, 7) == 0) { tox_add_friend_norequest(t, public_key); + } } uint32_t messages_received; @@ -58,14 +59,22 @@ START_TEST(test_few_clients) tox_callback_friend_request(tox2, accept_friend_request, tox2); uint8_t address[TOX_FRIEND_ADDRESS_SIZE]; tox_get_address(tox2, address); - int test = tox_add_friend(tox3, address, "Gentoo", 7); + int test = tox_add_friend(tox3, address, (uint8_t *)"Gentoo", 7); ck_assert_msg(test == 0, "Failed to add friend error code: %i", test); + uint8_t off = 1; + while (1) { tox_do(tox1); tox_do(tox2); tox_do(tox3); + if (tox_isconnected(tox1) && tox_isconnected(tox2) && tox_isconnected(tox3) && off) { + printf("Toxes are online, took %llu seconds\n", time(NULL) - cur_time); + off = 0; + } + + if (tox_get_friend_connection_status(tox2, 0) == 1 && tox_get_friend_connection_status(tox3, 0) == 1) break; @@ -75,7 +84,7 @@ START_TEST(test_few_clients) printf("tox clients connected\n"); uint32_t to_compare = 974536; tox_callback_friend_message(tox3, print_message, &to_compare); - tox_send_message(tox2, 0, "Install Gentoo", sizeof("Install Gentoo")); + tox_send_message(tox2, 0, (uint8_t *)"Install Gentoo", sizeof("Install Gentoo")); while (1) { messages_received = 0; @@ -92,7 +101,7 @@ START_TEST(test_few_clients) printf("tox clients messaging succeeded\n"); tox_callback_name_change(tox3, print_nickchange, &to_compare); - tox_set_name(tox2, "Gentoo", sizeof("Gentoo")); + tox_set_name(tox2, (uint8_t *)"Gentoo", sizeof("Gentoo")); while (1) { name_changes = 0; @@ -113,8 +122,8 @@ START_TEST(test_few_clients) } END_TEST -#define NUM_TOXES 66 -#define NUM_FRIENDS 20 +#define NUM_TOXES 33 +#define NUM_FRIENDS 10 START_TEST(test_many_clients) { @@ -140,7 +149,7 @@ loop_top: pairs[i].tox1 = rand() % NUM_TOXES; pairs[i].tox2 = (pairs[i].tox1 + rand() % (NUM_TOXES - 1) + 1) % NUM_TOXES; tox_get_address(toxes[pairs[i].tox1], address); - int test = tox_add_friend(toxes[pairs[i].tox2], address, "Gentoo", 7); + int test = tox_add_friend(toxes[pairs[i].tox2], address, (uint8_t *)"Gentoo", 7); if (test == TOX_FAERR_ALREADYSENT) { goto loop_top; diff --git a/docs/Prevent_Tracking.txt b/docs/Prevent_Tracking.txt index 5f7aaf1e..07e8ae1e 100644 --- a/docs/Prevent_Tracking.txt +++ b/docs/Prevent_Tracking.txt @@ -97,7 +97,8 @@ 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][data to send back in response(fixed size)]] +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][public key that we want those sending back data packets to use.][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, @@ -105,7 +106,7 @@ add the part used to send data to our list (if the list is full make it replace data to route request packet: [uint8_t packet id (133)][public key of destination node][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] +encrypted with that temporary private key and the nonce and the public key from the announce response packet 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] @@ -114,12 +115,13 @@ encrypted with real private key of the sender, the nonce in the data packet and Data sent to us: announce response packet: [uint8_t packet id (132)][data to send back in response(fixed size)][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)]] -(if the ping id is zero, it means the information to reach the client id we are searching for is stored on this node) +encrypted with the DHT private key of Node D, the public key in the request and the nonce:[[uint8_t is_stored] +[(32 bytes) ping_id if is_stored is 0, public key that must be used to send data packets if is_stored is not 0][Node_Format * (maximum of 8)]] +(if the is_stored is not 0, it means the information to reach the client id we are searching for is stored on this node) 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] +encrypted with that temporary private key, the nonce and the public key from the announce response packet of the destination node:[data] Onion packet (response): @@ -145,3 +147,11 @@ encrypted with temp symmetric key of Node A: [IP_Port (of us)][data to send back (sent from node A to us): [data to send back] + + +Data packets: + +To tell our friend what our DHT public key is so that he can connect to us we send a data packet with id 156 and +the data being:[uint64_t (in network byte order) no_replay, the packet will only be accepted if this number is bigger than the last one recieved] +[our dht public key][Node_Format * (maximum of 8) nodes closest to us so that the friend can find us faster] + diff --git a/docs/updates/Crypto.md b/docs/updates/Crypto.md index 6b489c3b..a6c701d3 100644 --- a/docs/updates/Crypto.md +++ b/docs/updates/Crypto.md @@ -20,7 +20,7 @@ case 1: Alice adds Bobs public key and bob waits for Alice to attempt to connect case 2: Bob and Alice add their respective public keys to their friends list at the same time. case 1: -Alice sends a crypto request packet to bob with the encrypted part containing the friends request like so: +Alice sends a onion data (see: Prevent_tracking.txt) packet to bob with the encrypted part containing the friends request like so: ``` [char with a value of 32][nospam number (4 bytes)][Message] ``` diff --git a/other/DHT_bootstrap.c b/other/DHT_bootstrap.c index 6561fe70..479e97a6 100644 --- a/other/DHT_bootstrap.c +++ b/other/DHT_bootstrap.c @@ -102,9 +102,19 @@ int main(int argc, char *argv[]) ip_init(&ip, ipv6enabled); DHT *dht = new_DHT(new_net_crypto(new_networking(ip, PORT))); + Onion *onion = new_onion(dht); + Onion_Announce *onion_a = new_onion_announce(dht); + + if (!(onion && onion_a)) { + printf("Something failed to initialize.\n"); + exit(1); + } perror("Initialization"); manage_keys(dht); + /* We want our DHT public key to be the same as our internal one since this is a bootstrap server */ + memcpy(dht->self_public_key, dht->c->self_public_key, crypto_box_PUBLICKEYBYTES); + memcpy(dht->self_secret_key, dht->c->self_secret_key, crypto_box_SECRETKEYBYTES); printf("Public key: "); uint32_t i; @@ -152,7 +162,7 @@ int main(int argc, char *argv[]) do_DHT(dht); if (is_timeout(last_LANdiscovery, is_waiting_for_dht_connection ? 5 : LAN_DISCOVERY_INTERVAL)) { - send_LANdiscovery(htons(PORT), dht->c); + send_LANdiscovery(htons(PORT), dht); last_LANdiscovery = unix_time(); } diff --git a/toxcore/DHT.c b/toxcore/DHT.c index 454047db..61ec5034 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c @@ -28,7 +28,11 @@ #endif #include "DHT.h" + +#ifdef ENABLE_ASSOC_DHT #include "assoc.h" +#endif + #include "ping.h" #include "network.h" @@ -285,7 +289,7 @@ static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nod */ sa_family_t ip_treat_as_family = client_ip->family; - if ((dht->c->lossless_udp->net->family == AF_INET6) && + if ((dht->net->family == AF_INET6) && (client_ip->family == AF_INET6)) { /* socket is AF_INET6, address claims AF_INET6: * check for embedded IPv4-in-IPv6 (shouldn't happen anymore, @@ -304,7 +308,8 @@ static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nod if (LAN_ip(ipptp->ip_port.ip) == 0 && !is_LAN) continue; - if (want_good && hardening_correct(&ipptp->hardening) != HARDENING_ALL_OK && !id_equal(client_id, client->client_id)) + if (LAN_ip(ipptp->ip_port.ip) != 0 && want_good && hardening_correct(&ipptp->hardening) != HARDENING_ALL_OK + && !id_equal(client_id, client->client_id)) continue; if (num_nodes < MAX_SENT_NODES) { @@ -355,10 +360,16 @@ static int get_somewhat_close_nodes(DHT *dht, uint8_t *client_id, Node_format *n get_close_nodes_inner(dht, client_id, nodes_list, sa_family, dht->close_clientlist, LCLIENT_LIST, &num_nodes, is_LAN, want_good); + /*TODO uncomment this when hardening is added to close friend clients + for (i = 0; i < dht->num_friends; ++i) + get_close_nodes_inner(dht, client_id, nodes_list, sa_family, + dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, + &num_nodes, is_LAN, want_good); + */ for (i = 0; i < dht->num_friends; ++i) get_close_nodes_inner(dht, client_id, nodes_list, sa_family, dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, - &num_nodes, is_LAN, want_good); + &num_nodes, is_LAN, 0); return num_nodes; } @@ -366,9 +377,13 @@ static int get_somewhat_close_nodes(DHT *dht, uint8_t *client_id, Node_format *n int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_family_t sa_family, uint8_t is_LAN, uint8_t want_good) { +#ifdef ENABLE_ASSOC_DHT + if (!dht->assoc) +#endif return get_somewhat_close_nodes(dht, client_id, nodes_list, sa_family, is_LAN, want_good); +#ifdef ENABLE_ASSOC_DHT Client_data *result[MAX_SENT_NODES]; Assoc_close_entries request; @@ -420,6 +435,7 @@ int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_fa } return num_returned; +#endif } /* Replace first bad (or empty) node with this one. @@ -566,7 +582,7 @@ static int replace_good( Client_data *list, if ((ip_port.ip.family != AF_INET) && (ip_port.ip.family != AF_INET6)) return 1; - sort_list(list, length, comp_client_id); + //sort_list(list, length, comp_client_id); int8_t replace = -1; @@ -636,10 +652,10 @@ int addto_lists(DHT *dht, IP_Port ip_port, uint8_t *client_id) if (!client_or_ip_port_in_list(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port)) { if (replace_bad(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port)) { if (replace_possible_bad(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port, - dht->c->self_public_key)) { + dht->self_public_key)) { /* If we can't replace bad nodes we try replacing good ones. */ if (!replace_good(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port, - dht->c->self_public_key)) + dht->self_public_key)) used++; } else used++; @@ -669,6 +685,8 @@ int addto_lists(DHT *dht, IP_Port ip_port, uint8_t *client_id) used++; } +#ifdef ENABLE_ASSOC_DHT + if (dht->assoc) { IPPTs ippts; @@ -678,6 +696,7 @@ int addto_lists(DHT *dht, IP_Port ip_port, uint8_t *client_id) Assoc_add_entry(dht->assoc, client_id, &ippts, NULL, used ? 1 : 0); } +#endif return used; } @@ -697,7 +716,7 @@ static int returnedip_ports(DHT *dht, IP_Port ip_port, uint8_t *client_id, uint8 ip_port.ip.ip4.uint32 = ip_port.ip.ip6.uint32[3]; } - if (id_equal(client_id, dht->c->self_public_key)) { + if (id_equal(client_id, dht->self_public_key)) { for (i = 0; i < LCLIENT_LIST; ++i) { if (id_equal(nodeclient_id, dht->close_clientlist[i].client_id)) { if (ip_port.ip.family == AF_INET) { @@ -734,6 +753,7 @@ static int returnedip_ports(DHT *dht, IP_Port ip_port, uint8_t *client_id, uint8 } end: +#ifdef ENABLE_ASSOC_DHT if (dht->assoc) { IPPTs ippts; @@ -744,6 +764,7 @@ end: Assoc_add_entry(dht->assoc, client_id, &ippts, NULL, used ? 1 : 0); } +#endif return 0; } @@ -754,7 +775,7 @@ end: static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, Node_format *sendback_node) { /* Check if packet is going to be sent to ourself. */ - if (id_equal(public_key, dht->c->self_public_key)) + if (id_equal(public_key, dht->self_public_key)) return -1; uint8_t plain_message[NODES_ENCRYPTED_MESSAGE_LENGTH] = {0}; @@ -794,7 +815,7 @@ static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cli memcpy(plain + CLIENT_ID_SIZE, encrypted_message, NODES_ENCRYPTED_MESSAGE_LENGTH); int len = encrypt_data( public_key, - dht->c->self_secret_key, + dht->self_secret_key, nonce, plain, CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH, @@ -804,11 +825,11 @@ static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cli return -1; data[0] = NET_PACKET_GET_NODES; - memcpy(data + 1, dht->c->self_public_key, CLIENT_ID_SIZE); + memcpy(data + 1, dht->self_public_key, CLIENT_ID_SIZE); memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); - return sendpacket(dht->c->lossless_udp->net, ip_port, data, sizeof(data)); + return sendpacket(dht->net, ip_port, data, sizeof(data)); } /* Send a send nodes response. */ @@ -818,7 +839,7 @@ static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cli static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint8_t *encrypted_data) { /* Check if packet is going to be sent to ourself. */ - if (id_equal(public_key, dht->c->self_public_key)) + if (id_equal(public_key, dht->self_public_key)) return -1; size_t Node4_format_size = sizeof(Node4_format); @@ -863,7 +884,7 @@ static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cl memcpy(plain + num_nodes * Node4_format_size, encrypted_data, NODES_ENCRYPTED_MESSAGE_LENGTH); int len = encrypt_data( public_key, - dht->c->self_secret_key, + dht->self_secret_key, nonce, plain, num_nodes * Node4_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH, @@ -874,11 +895,11 @@ static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cl return -1; data[0] = NET_PACKET_SEND_NODES; - memcpy(data + 1, dht->c->self_public_key, CLIENT_ID_SIZE); + memcpy(data + 1, dht->self_public_key, CLIENT_ID_SIZE); memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); - return sendpacket(dht->c->lossless_udp->net, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len); + return sendpacket(dht->net, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len); } void to_net_family(IP *ip) @@ -904,7 +925,7 @@ void to_host_family(IP *ip) static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint8_t *encrypted_data) { /* Check if packet is going to be sent to ourself. */ - if (id_equal(public_key, dht->c->self_public_key)) + if (id_equal(public_key, dht->self_public_key)) return -1; size_t Node_format_size = sizeof(Node_format); @@ -930,7 +951,7 @@ static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_ memcpy(plain, nodes_list, num_nodes * Node_format_size); memcpy(plain + num_nodes * Node_format_size, encrypted_data, NODES_ENCRYPTED_MESSAGE_LENGTH); int len = encrypt_data( public_key, - dht->c->self_secret_key, + dht->self_secret_key, nonce, plain, num_nodes * Node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH, @@ -940,11 +961,11 @@ static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_ return -1; data[0] = NET_PACKET_SEND_NODES_IPV6; - memcpy(data + 1, dht->c->self_public_key, CLIENT_ID_SIZE); + memcpy(data + 1, dht->self_public_key, CLIENT_ID_SIZE); memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); - return sendpacket(dht->c->lossless_udp->net, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len); + return sendpacket(dht->net, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len); } static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length) @@ -956,13 +977,13 @@ static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32 return 1; /* Check if packet is from ourself. */ - if (id_equal(packet + 1, dht->c->self_public_key)) + if (id_equal(packet + 1, dht->self_public_key)) return 1; uint8_t plain[CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH]; int len = decrypt_data( packet + 1, - dht->c->self_secret_key, + dht->self_secret_key, packet + 1 + CLIENT_ID_SIZE, packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES, @@ -1038,7 +1059,7 @@ static int handle_sendnodes_core(void *object, IP_Port source, uint8_t *packet, int len = decrypt_data( packet + 1, - dht->c->self_secret_key, + dht->self_secret_key, packet + 1 + CLIENT_ID_SIZE, packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, num_nodes * node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES, @@ -1140,6 +1161,7 @@ static int handle_sendnodes_ipv6(void *object, IP_Port source, uint8_t *packet, /* * Send get nodes requests with client_id to max_num peers in list of length length */ +/* static void get_bunchnodes(DHT *dht, Client_data *list, uint16_t length, uint16_t max_num, uint8_t *client_id) { uint32_t i, num = 0; @@ -1159,7 +1181,7 @@ static void get_bunchnodes(DHT *dht, Client_data *list, uint16_t length, uint16_ } } } - +*/ int DHT_addfriend(DHT *dht, uint8_t *client_id) { if (friend_number(dht, client_id) != -1) /* Is friend already in DHT? */ @@ -1177,6 +1199,7 @@ int DHT_addfriend(DHT *dht, uint8_t *client_id) dht->friends_list[dht->num_friends].nat.NATping_id = random_64b(); ++dht->num_friends; +#ifdef ENABLE_ASSOC_DHT if (dht->assoc) { /* get up to MAX_FRIEND_CLIENTS connectable nodes */ @@ -1206,8 +1229,9 @@ int DHT_addfriend(DHT *dht, uint8_t *client_id) } } - /*TODO: make this better?*/ - get_bunchnodes(dht, dht->close_clientlist, LCLIENT_LIST, MAX_FRIEND_CLIENTS, client_id); +#endif + /*this isn't really useful anymore. + get_bunchnodes(dht, dht->close_clientlist, LCLIENT_LIST, MAX_FRIEND_CLIENTS, client_id);*/ return 0; } @@ -1343,7 +1367,7 @@ static void do_DHT_friends(DHT *dht) */ static void do_Close(DHT *dht) { - uint8_t not_killed = do_ping_and_sendnode_requests(dht, &dht->close_lastgetnodes, dht->c->self_public_key, + uint8_t not_killed = do_ping_and_sendnode_requests(dht, &dht->close_lastgetnodes, dht->self_public_key, dht->close_clientlist, LCLIENT_LIST); if (!not_killed) { @@ -1374,16 +1398,17 @@ void DHT_getnodes(DHT *dht, IP_Port *from_ipp, uint8_t *from_id, uint8_t *which_ void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key) { - /* + /*#ifdef ENABLE_ASSOC_DHT if (dht->assoc) { IPPTs ippts; ippts.ip_port = ip_port; ippts.timestamp = 0; Assoc_add_entry(dht->assoc, public_key, &ippts, NULL, 0); - }*/ + } + #endif*/ - getnodes(dht, ip_port, public_key, dht->c->self_public_key, NULL); + getnodes(dht, ip_port, public_key, dht->self_public_key, NULL); } int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enabled, uint16_t port, uint8_t *public_key) @@ -1427,9 +1452,9 @@ int route_packet(DHT *dht, uint8_t *client_id, uint8_t *packet, uint32_t length) Client_data *client = &dht->close_clientlist[i]; if (ip_isset(&client->assoc6.ip_port.ip)) - return sendpacket(dht->c->lossless_udp->net, client->assoc6.ip_port, packet, length); + return sendpacket(dht->net, client->assoc6.ip_port, packet, length); else if (ip_isset(&client->assoc4.ip_port.ip)) - return sendpacket(dht->c->lossless_udp->net, client->assoc4.ip_port, packet, length); + return sendpacket(dht->net, client->assoc4.ip_port, packet, length); else break; } @@ -1552,7 +1577,7 @@ int route_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint32_t lengt /* If ip is not zero and node is good. */ if (ip_isset(&assoc->ret_ip_port.ip) && !is_timeout(assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { - int retval = sendpacket(dht->c->lossless_udp->net, assoc->ip_port, packet, length); + int retval = sendpacket(dht->net, assoc->ip_port, packet, length); if ((unsigned int)retval == length) { ++sent; @@ -1606,7 +1631,7 @@ static int routeone_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint if (n < 1) return 0; - int retval = sendpacket(dht->c->lossless_udp->net, ip_list[rand() % n], packet, length); + int retval = sendpacket(dht->net, ip_list[rand() % n], packet, length); if ((unsigned int)retval == length) return 1; @@ -1647,7 +1672,7 @@ static int send_NATping(DHT *dht, uint8_t *public_key, uint64_t ping_id, uint8_t data[0] = type; memcpy(data + 1, &ping_id, sizeof(uint64_t)); /* 254 is NAT ping request packet id */ - int len = create_request(dht->c->self_public_key, dht->c->self_secret_key, packet, public_key, data, + int len = create_request(dht->self_public_key, dht->self_secret_key, packet, public_key, data, sizeof(uint64_t) + 1, CRYPTO_PACKET_NAT_PING); if (len == -1) @@ -1821,7 +1846,7 @@ static void do_NAT(DHT *dht) /*----------------------------------------------------------------------------------*/ /*-----------------------END OF NAT PUNCHING FUNCTIONS------------------------------*/ -#define HARDREQ_DATA_SIZE 768 /* Attempt to prevent amplification/other attacks*/ +#define HARDREQ_DATA_SIZE 384 /* Attempt to prevent amplification/other attacks*/ #define CHECK_TYPE_ROUTE_REQ 0 #define CHECK_TYPE_ROUTE_RES 1 @@ -1839,13 +1864,13 @@ static int send_hardening_req(DHT *dht, Node_format *sendto, uint8_t type, uint8 uint8_t data[HARDREQ_DATA_SIZE] = {0}; data[0] = type; memcpy(data + 1, contents, length); - int len = create_request(dht->c->self_public_key, dht->c->self_secret_key, packet, sendto->client_id, data, + int len = create_request(dht->self_public_key, dht->self_secret_key, packet, sendto->client_id, data, sizeof(data), CRYPTO_PACKET_HARDENING); if (len == -1) return -1; - return sendpacket(dht->c->lossless_udp->net, sendto->ip_port, packet, len); + return sendpacket(dht->net, sendto->ip_port, packet, len); } /* Send a get node hardening request */ @@ -1869,13 +1894,13 @@ static int send_hardening_getnode_res(DHT *dht, Node_format *sendto, uint8_t *qu data[0] = CHECK_TYPE_GETNODE_RES; memcpy(data + 1, queried_client_id, CLIENT_ID_SIZE); memcpy(data + 1 + CLIENT_ID_SIZE, list, num_nodes * sizeof(Node_format)); - int len = create_request(dht->c->self_public_key, dht->c->self_secret_key, packet, sendto->client_id, data, + int len = create_request(dht->self_public_key, dht->self_secret_key, packet, sendto->client_id, data, sizeof(data), CRYPTO_PACKET_HARDENING); if (len == -1) return -1; - return sendpacket(dht->c->lossless_udp->net, sendto->ip_port, packet, len); + return sendpacket(dht->net, sendto->ip_port, packet, len); } /* TODO: improve */ @@ -1906,7 +1931,7 @@ static uint32_t have_nodes_closelist(DHT *dht, Node_format *nodes, uint16_t num) uint32_t i; for (i = 0; i < num; ++i) { - if (id_equal(nodes[i].client_id, dht->c->self_public_key)) { + if (id_equal(nodes[i].client_id, dht->self_public_key)) { ++counter; continue; } @@ -2116,7 +2141,7 @@ uint16_t random_nodes_path(DHT *dht, Node_format *nodes, uint16_t max_num) uint32_t i; for (i = 0; i < max_num; ++i) { - uint16_t rand_num = rand() % dht->num_friends + 1; + uint16_t rand_num = rand() % (dht->num_friends + 1); if (rand_num == dht->num_friends) { list = dht->close_clientlist; @@ -2173,7 +2198,7 @@ void do_hardening(DHT *dht) memcpy(to_test.client_id, client_id, CLIENT_ID_SIZE); //TODO: The search id should maybe not be ours? - if (send_hardening_getnode_req(dht, &rand_node, &to_test, dht->c->self_public_key) > 0) { + if (send_hardening_getnode_req(dht, &rand_node, &to_test, dht->self_public_key) > 0) { memcpy(cur_iptspng->hardening.send_nodes_pingedid, rand_node.client_id, CLIENT_ID_SIZE); cur_iptspng->hardening.send_nodes_timestamp = unix_time(); } @@ -2203,24 +2228,34 @@ DHT *new_DHT(Net_Crypto *c) if (dht == NULL) return NULL; - dht->ping = new_ping(dht, c); + dht->c = c; + dht->net = c->lossless_udp->net; + dht->ping = new_ping(dht); if (dht->ping == NULL) { kill_DHT(dht); return NULL; } - dht->c = c; - networking_registerhandler(c->lossless_udp->net, NET_PACKET_GET_NODES, &handle_getnodes, dht); - networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES, &handle_sendnodes, dht); - networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES_IPV6, &handle_sendnodes_ipv6, dht); + networking_registerhandler(dht->net, NET_PACKET_GET_NODES, &handle_getnodes, dht); + networking_registerhandler(dht->net, NET_PACKET_SEND_NODES, &handle_sendnodes, dht); + networking_registerhandler(dht->net, NET_PACKET_SEND_NODES_IPV6, &handle_sendnodes_ipv6, dht); init_cryptopackets(dht); cryptopacket_registerhandler(c, CRYPTO_PACKET_NAT_PING, &handle_NATping, dht); cryptopacket_registerhandler(c, CRYPTO_PACKET_HARDENING, &handle_hardening, dht); new_symmetric_key(dht->secret_symmetric_key); crypto_box_keypair(dht->self_public_key, dht->self_secret_key); - dht->assoc = new_Assoc_default(dht->c->self_public_key); +#ifdef ENABLE_ASSOC_DHT + dht->assoc = new_Assoc_default(dht->self_public_key); +#endif + uint32_t i; + + for (i = 0; i < DHT_FAKE_FRIEND_NUMBER; ++i) { + uint8_t random_key_bytes[CLIENT_ID_SIZE]; + randombytes(random_key_bytes, sizeof(random_key_bytes)); + DHT_addfriend(dht, random_key_bytes); + } return dht; } @@ -2238,15 +2273,19 @@ void do_DHT(DHT *dht) do_NAT(dht); do_toping(dht->ping); do_hardening(dht); +#ifdef ENABLE_ASSOC_DHT if (dht->assoc) do_Assoc(dht->assoc, dht); +#endif dht->last_run = unix_time(); } void kill_DHT(DHT *dht) { +#ifdef ENABLE_ASSOC_DHT kill_Assoc(dht->assoc); +#endif kill_ping(dht->ping); free(dht->friends_list); free(dht); diff --git a/toxcore/DHT.h b/toxcore/DHT.h index 5afc8ce8..eb889d5d 100644 --- a/toxcore/DHT.h +++ b/toxcore/DHT.h @@ -56,6 +56,9 @@ #define TOX_AF_INET 2 #define TOX_AF_INET6 10 +/* The number of "fake" friends to add (for optimization purposes and so our paths for the onion part are more random) */ +#define DHT_FAKE_FRIEND_NUMBER 4 + /* Functions to transfer ips safely across wire. */ void to_net_family(IP *ip); void to_host_family(IP *ip); @@ -139,6 +142,7 @@ typedef struct { typedef struct { Net_Crypto *c; + Networking_Core *net; Client_data close_clientlist[LCLIENT_LIST]; uint64_t close_lastgetnodes; @@ -153,9 +157,9 @@ typedef struct { uint16_t num_friends; struct PING *ping; - +#ifdef ENABLE_ASSOC_DHT struct Assoc *assoc; - +#endif uint64_t last_run; } DHT; /*----------------------------------------------------------------------------------*/ diff --git a/toxcore/LAN_discovery.c b/toxcore/LAN_discovery.c index eadec9ec..bed14754 100644 --- a/toxcore/LAN_discovery.c +++ b/toxcore/LAN_discovery.c @@ -220,33 +220,33 @@ static int handle_LANdiscovery(void *object, IP_Port source, uint8_t *packet, ui } -int send_LANdiscovery(uint16_t port, Net_Crypto *c) +int send_LANdiscovery(uint16_t port, DHT *dht) { uint8_t data[crypto_box_PUBLICKEYBYTES + 1]; data[0] = NET_PACKET_LAN_DISCOVERY; - id_copy(data + 1, c->self_public_key); + id_copy(data + 1, dht->self_public_key); #ifdef __linux - send_broadcasts(c->lossless_udp->net, port, data, 1 + crypto_box_PUBLICKEYBYTES); + send_broadcasts(dht->net, port, data, 1 + crypto_box_PUBLICKEYBYTES); #endif int res = -1; IP_Port ip_port; ip_port.port = port; /* IPv6 multicast */ - if (c->lossless_udp->net->family == AF_INET6) { + if (dht->net->family == AF_INET6) { ip_port.ip = broadcast_ip(AF_INET6, AF_INET6); if (ip_isset(&ip_port.ip)) - if (sendpacket(c->lossless_udp->net, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES) > 0) + if (sendpacket(dht->net, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES) > 0) res = 1; } /* IPv4 broadcast (has to be IPv4-in-IPv6 mapping if socket is AF_INET6 */ - ip_port.ip = broadcast_ip(c->lossless_udp->net->family, AF_INET); + ip_port.ip = broadcast_ip(dht->net->family, AF_INET); if (ip_isset(&ip_port.ip)) - if (sendpacket(c->lossless_udp->net, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES)) + if (sendpacket(dht->net, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES)) res = 1; return res; @@ -255,5 +255,5 @@ int send_LANdiscovery(uint16_t port, Net_Crypto *c) void LANdiscovery_init(DHT *dht) { - networking_registerhandler(dht->c->lossless_udp->net, NET_PACKET_LAN_DISCOVERY, &handle_LANdiscovery, dht); + networking_registerhandler(dht->net, NET_PACKET_LAN_DISCOVERY, &handle_LANdiscovery, dht); } diff --git a/toxcore/LAN_discovery.h b/toxcore/LAN_discovery.h index 9d19114d..58bd2bee 100644 --- a/toxcore/LAN_discovery.h +++ b/toxcore/LAN_discovery.h @@ -39,7 +39,7 @@ #define LAN_DISCOVERY_INTERVAL 60 /* Send a LAN discovery pcaket to the broadcast address with port port. */ -int send_LANdiscovery(uint16_t port, Net_Crypto *c); +int send_LANdiscovery(uint16_t port, DHT *dht); /* Sets up packet handlers. */ void LANdiscovery_init(DHT *dht); diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index bb3a56f0..19246d7d 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -34,27 +34,6 @@ #define MIN(a,b) (((a)<(b))?(a):(b)) -void host_to_net(uint8_t *num, uint16_t numbytes) -{ - union { - uint32_t i; - uint8_t c[4]; - } a; - a.i = 1; - - if (a.c[0] == 1) { - uint32_t i; - uint8_t buff[numbytes]; - - for (i = 0; i < numbytes; ++i) { - buff[i] = num[numbytes - i - 1]; - } - - memcpy(num, buff, numbytes); - } -} -#define net_to_host(x, y) host_to_net(x, y) - static void set_friend_status(Messenger *m, int friendnumber, uint8_t status); static int write_cryptpacket_id(Messenger *m, int friendnumber, uint8_t packet_id, uint8_t *data, uint32_t length); @@ -206,11 +185,16 @@ int m_addfriend(Messenger *m, uint8_t *address, uint8_t *data, uint16_t length) memset(&(m->friendlist[m->numfriends]), 0, sizeof(Friend)); + int onion_friendnum = onion_addfriend(m->onion_c, client_id); + + if (onion_friendnum == -1) + return FAERR_UNKNOWN; + uint32_t i; for (i = 0; i <= m->numfriends; ++i) { if (m->friendlist[i].status == NOFRIEND) { - DHT_addfriend(m->dht, client_id); + m->friendlist[i].onion_friendnum = onion_friendnum; m->friendlist[i].status = FRIEND_ADDED; m->friendlist[i].crypt_connection_id = -1; m->friendlist[i].friendrequest_lastsent = 0; @@ -249,11 +233,16 @@ int m_addfriend_norequest(Messenger *m, uint8_t *client_id) memset(&(m->friendlist[m->numfriends]), 0, sizeof(Friend)); + int onion_friendnum = onion_addfriend(m->onion_c, client_id); + + if (onion_friendnum == -1) + return FAERR_UNKNOWN; + uint32_t i; for (i = 0; i <= m->numfriends; ++i) { if (m->friendlist[i].status == NOFRIEND) { - DHT_addfriend(m->dht, client_id); + m->friendlist[i].onion_friendnum = onion_friendnum; m->friendlist[i].status = FRIEND_CONFIRMED; m->friendlist[i].crypt_connection_id = -1; m->friendlist[i].friendrequest_lastsent = 0; @@ -284,7 +273,7 @@ int m_delfriend(Messenger *m, int friendnumber) if (friend_not_valid(m, friendnumber)) return -1; - DHT_delfriend(m->dht, m->friendlist[friendnumber].client_id); + onion_delfriend(m->onion_c, m->friendlist[friendnumber].onion_friendnum); crypto_kill(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id); free(m->friendlist[friendnumber].statusmessage); memset(&(m->friendlist[friendnumber]), 0, sizeof(Friend)); @@ -673,6 +662,8 @@ static void check_friend_connectionstatus(Messenger *m, int friendnumber, uint8_ const uint8_t was_online = m->friendlist[friendnumber].status == FRIEND_ONLINE; const uint8_t is_online = status == FRIEND_ONLINE; + onion_set_friend_online(m->onion_c, m->friendlist[friendnumber].onion_friendnum, is_online); + if (is_online != was_online) { if (was_online) break_files(m, friendnumber); @@ -1513,7 +1504,7 @@ static int friend_already_added(uint8_t *client_id, void *data) static void LANdiscovery(Messenger *m) { if (m->last_LANdiscovery + LAN_DISCOVERY_INTERVAL < unix_time()) { - send_LANdiscovery(htons(TOX_PORT_DEFAULT), m->net_crypto); + send_LANdiscovery(htons(TOX_PORT_DEFAULT), m->dht); m->last_LANdiscovery = unix_time(); } } @@ -1552,9 +1543,24 @@ Messenger *new_messenger(uint8_t ipv6enabled) return NULL; } + m->onion = new_onion(m->dht); + m->onion_a = new_onion_announce(m->dht); + m->onion_c = new_onion_client(m->dht); + + if (!(m->onion && m->onion_a && m->onion_c)) { + kill_onion(m->onion); + kill_onion_announce(m->onion_a); + kill_onion_client(m->onion_c); + kill_DHT(m->dht); + kill_net_crypto(m->net_crypto); + kill_networking(m->net); + free(m); + return NULL; + } + m_set_statusmessage(m, (uint8_t *)"Online", sizeof("Online")); - friendreq_init(&(m->fr), m->net_crypto); + friendreq_init(&(m->fr), m->onion_c); LANdiscovery_init(m->dht); set_nospam(&(m->fr), random_int()); set_filter_function(&(m->fr), &friend_already_added, m); @@ -1610,7 +1616,7 @@ void do_friends(Messenger *m) for (i = 0; i < m->numfriends; ++i) { if (m->friendlist[i].status == FRIEND_ADDED) { - int fr = send_friendrequest(m->dht, m->friendlist[i].client_id, m->friendlist[i].friendrequest_nospam, + int fr = send_friendrequest(m->onion_c, m->friendlist[i].client_id, m->friendlist[i].friendrequest_nospam, m->friendlist[i].info, m->friendlist[i].info_size); @@ -1630,7 +1636,7 @@ void do_friends(Messenger *m) } IP_Port friendip; - int friendok = DHT_getfriendip(m->dht, m->friendlist[i].client_id, &friendip); + int friendok = onion_getfriendip(m->onion_c, m->friendlist[i].onion_friendnum, &friendip); switch (is_cryptoconnected(m->net_crypto, m->friendlist[i].crypt_connection_id)) { case CRYPTO_CONN_NO_CONNECTION: @@ -1957,6 +1963,7 @@ void do_messenger(Messenger *m) do_DHT(m->dht); do_net_crypto(m->net_crypto); + do_onion_client(m->onion_c); do_friends(m); do_inbound(m); do_allgroupchats(m); @@ -2188,9 +2195,12 @@ static int messenger_load_state_callback(void *outer, uint8_t *data, uint32_t le if (length == crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t)) { set_nospam(&(m->fr), *(uint32_t *)data); load_keys(m->net_crypto, &data[sizeof(uint32_t)]); +#ifdef ENABLE_ASSOC_DHT if (m->dht->assoc) Assoc_self_client_id_changed(m->dht->assoc, m->net_crypto->self_public_key); + +#endif } else return -1; /* critical */ diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 3cfd5065..e09b2f30 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -31,6 +31,7 @@ #include "friend_requests.h" #include "LAN_discovery.h" #include "group_chats.h" +#include "onion_client.h" #define MAX_NAME_LENGTH 128 #define MAX_STATUSMESSAGE_LENGTH 1007 @@ -130,6 +131,7 @@ enum { typedef struct { uint8_t client_id[CLIENT_ID_SIZE]; + uint32_t onion_friendnum; int crypt_connection_id; uint64_t friendrequest_lastsent; // Time at which the last friend request was sent. uint32_t friendrequest_timeout; // The timeout between successful friendrequest sending attempts. @@ -160,6 +162,11 @@ typedef struct Messenger { Networking_Core *net; Net_Crypto *net_crypto; DHT *dht; + + Onion *onion; + Onion_Announce *onion_a; + Onion_Client *onion_c; + Friend_Requests fr; uint8_t name[MAX_NAME_LENGTH]; uint16_t name_length; diff --git a/toxcore/friend_requests.c b/toxcore/friend_requests.c index 589bd315..5c294c76 100644 --- a/toxcore/friend_requests.c +++ b/toxcore/friend_requests.c @@ -35,41 +35,24 @@ * return 0 if it sent the friend request directly to the friend. * return the number of peers it was routed through if it did not send it directly. */ -int send_friendrequest(DHT *dht, uint8_t *public_key, uint32_t nospam_num, uint8_t *data, uint32_t length) +int send_friendrequest(Onion_Client *onion_c, uint8_t *public_key, uint32_t nospam_num, uint8_t *data, uint32_t length) { if (length + sizeof(nospam_num) > MAX_DATA_SIZE) return -1; uint8_t temp[MAX_DATA_SIZE]; - memcpy(temp, &nospam_num, sizeof(nospam_num)); - memcpy(temp + sizeof(nospam_num), data, length); - uint8_t packet[MAX_DATA_SIZE]; - int len = create_request(dht->c->self_public_key, dht->c->self_secret_key, packet, public_key, temp, - length + sizeof(nospam_num), - CRYPTO_PACKET_FRIEND_REQ); + temp[0] = CRYPTO_PACKET_FRIEND_REQ; + memcpy(temp + 1, &nospam_num, sizeof(nospam_num)); + memcpy(temp + 1 + sizeof(nospam_num), data, length); - if (len == -1) + int friend_num = onion_friend_num(onion_c, public_key); + + if (friend_num == -1) return -1; - IP_Port ip_port; - int friendok = DHT_getfriendip(dht, public_key, &ip_port); + int num = send_onion_data(onion_c, friend_num, temp, 1 + sizeof(nospam_num) + length); - // not a friend - if (friendok == -1) - return -1; - - // is a friend and we know how to reach him - if (friendok == 1) { - if (sendpacket(dht->c->lossless_udp->net, ip_port, packet, len) != -1) - return 0; - - return -1; - } - - // is a friend, we DON'T know how to reach him - int num = route_tofriend(dht, public_key, packet, len); - - if (num == 0) + if (num <= 0) return -1; return num; @@ -130,9 +113,14 @@ static int request_received(Friend_Requests *fr, uint8_t *client_id) } -static int friendreq_handlepacket(void *object, IP_Port source, uint8_t *source_pubkey, uint8_t *packet, - uint32_t length) +static int friendreq_handlepacket(void *object, uint8_t *source_pubkey, uint8_t *packet, uint32_t length) { + if (length == 0) + return 1; + + ++packet; + --length; + Friend_Requests *fr = object; if (fr->handle_friendrequest_isset == 0) @@ -156,7 +144,7 @@ static int friendreq_handlepacket(void *object, IP_Port source, uint8_t *source_ return 0; } -void friendreq_init(Friend_Requests *fr, Net_Crypto *c) +void friendreq_init(Friend_Requests *fr, Onion_Client *onion_c) { - cryptopacket_registerhandler(c, CRYPTO_PACKET_FRIEND_REQ, &friendreq_handlepacket, fr); + oniondata_registerhandler(onion_c, CRYPTO_PACKET_FRIEND_REQ, &friendreq_handlepacket, fr); } diff --git a/toxcore/friend_requests.h b/toxcore/friend_requests.h index c655669d..732dc4a2 100644 --- a/toxcore/friend_requests.h +++ b/toxcore/friend_requests.h @@ -24,7 +24,7 @@ #ifndef FRIEND_REQUESTS_H #define FRIEND_REQUESTS_H -#include "DHT.h" +#include "onion_client.h" #include "net_crypto.h" @@ -49,7 +49,7 @@ typedef struct { /* Try to send a friendrequest to peer with public_key. * data is the data in the request and length is the length. */ -int send_friendrequest(DHT *dht, uint8_t *public_key, uint32_t nospam_num, uint8_t *data, uint32_t length); +int send_friendrequest(Onion_Client *onion_c, uint8_t *public_key, uint32_t nospam_num, uint8_t *data, uint32_t length); /* Set and get the nospam variable used to prevent one type of friend request spam. */ void set_nospam(Friend_Requests *fr, uint32_t num); uint32_t get_nospam(Friend_Requests *fr); @@ -67,7 +67,7 @@ void callback_friendrequest(Friend_Requests *fr, void (*function)(uint8_t *, uin void set_filter_function(Friend_Requests *fr, int (*function)(uint8_t *, void *), void *userdata); /* Sets up friendreq packet handlers. */ -void friendreq_init(Friend_Requests *fr, Net_Crypto *c); +void friendreq_init(Friend_Requests *fr, Onion_Client *onion_c); #endif diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index a6c3ecd9..5c2691f3 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -365,11 +365,11 @@ static int cryptopacket_handle(void *object, IP_Port source, uint8_t *packet, ui length > MAX_DATA_SIZE + crypto_box_MACBYTES) return 1; - if (memcmp(packet + 1, dht->c->self_public_key, crypto_box_PUBLICKEYBYTES) == 0) { // Check if request is for us. + if (memcmp(packet + 1, dht->self_public_key, crypto_box_PUBLICKEYBYTES) == 0) { // Check if request is for us. uint8_t public_key[crypto_box_PUBLICKEYBYTES]; uint8_t data[MAX_DATA_SIZE]; uint8_t number; - int len = handle_request(dht->c->self_public_key, dht->c->self_secret_key, public_key, data, &number, packet, length); + int len = handle_request(dht->self_public_key, dht->self_secret_key, public_key, data, &number, packet, length); if (len == -1 || len == 0) return 1; diff --git a/toxcore/onion.c b/toxcore/onion.c index 7ec6bb61..9819762d 100644 --- a/toxcore/onion.c +++ b/toxcore/onion.c @@ -363,6 +363,9 @@ Onion *new_onion(DHT *dht) void kill_onion(Onion *onion) { + if (onion == NULL) + return; + networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_INITIAL, NULL, NULL); networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_1, NULL, NULL); networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_2, NULL, NULL); diff --git a/toxcore/onion_announce.c b/toxcore/onion_announce.c index 92c9e940..8150974b 100644 --- a/toxcore/onion_announce.c +++ b/toxcore/onion_announce.c @@ -29,7 +29,7 @@ #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 + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_MACBYTES) #define ANNOUNCE_REQUEST_SIZE_RECV (ANNOUNCE_REQUEST_SIZE + ONION_RETURN_3) #define DATA_REQUEST_MIN_SIZE (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES) @@ -43,6 +43,7 @@ * 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. + * data_public_key is the public key we want others to encrypt their data packets with. * sendback_data is the data of ONION_ANNOUNCE_SENDBACK_DATA_LENGTH length that we expect to * receive back in the response. * @@ -50,12 +51,14 @@ * 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 *sendback_data) + uint8_t *client_id, uint8_t *data_public_key, uint8_t *sendback_data) { - uint8_t plain[ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH]; + uint8_t plain[ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + 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); + memcpy(plain + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES, data_public_key, crypto_box_PUBLICKEYBYTES); + memcpy(plain + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + 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); @@ -78,12 +81,15 @@ 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. + * encrypt_public_key is the public key used to encrypt the data packet. + * * 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 *nonce, uint8_t *data, uint16_t length) +int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *encrypt_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; @@ -96,7 +102,7 @@ int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, random_public_key, crypto_box_PUBLICKEYBYTES); - int len = encrypt_data(public_key, random_secret_key, packet + 1 + crypto_box_PUBLICKEYBYTES, + int len = encrypt_data(encrypt_public_key, random_secret_key, packet + 1 + crypto_box_PUBLICKEYBYTES, data, length, packet + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES); if (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + (uint32_t)len != sizeof(packet)) @@ -167,10 +173,11 @@ static int cmp_entry(const void *a, const void *b) /* add entry to entries list * - * return 0 if failure - * return 1 if added + * return -1 if failure + * return position if added */ -static int add_to_entries(Onion_Announce *onion_a, IP_Port ret_ip_port, uint8_t *public_key, uint8_t *ret) +static int add_to_entries(Onion_Announce *onion_a, IP_Port ret_ip_port, uint8_t *public_key, uint8_t *data_public_key, + uint8_t *ret) { int pos = in_entries(onion_a, public_key); @@ -190,16 +197,17 @@ static int add_to_entries(Onion_Announce *onion_a, IP_Port ret_ip_port, uint8_t } if (pos == -1) - return 0; + return -1; memcpy(onion_a->entries[pos].public_key, public_key, crypto_box_PUBLICKEYBYTES); onion_a->entries[pos].ret_ip_port = ret_ip_port; memcpy(onion_a->entries[pos].ret, ret, ONION_RETURN_3); + memcpy(onion_a->entries[pos].data_public_key, data_public_key, crypto_box_PUBLICKEYBYTES); onion_a->entries[pos].time = unix_time(); memcpy(cmp_public_key, onion_a->dht->self_public_key, crypto_box_PUBLICKEYBYTES); qsort(onion_a->entries, ONION_ANNOUNCE_MAX_ENTRIES, sizeof(Onion_Announce_Entry), cmp_entry); - return 1; + return pos; } static int handle_announce_request(void *object, IP_Port source, uint8_t *packet, uint32_t length) @@ -209,10 +217,11 @@ static int handle_announce_request(void *object, IP_Port source, uint8_t *packet if (length != ANNOUNCE_REQUEST_SIZE_RECV) return 1; - uint8_t plain[ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH]; + uint8_t plain[ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + 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, - ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_MACBYTES, plain); + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + + crypto_box_MACBYTES, plain); if ((uint32_t)len != sizeof(plain)) return 1; @@ -223,13 +232,14 @@ static int handle_announce_request(void *object, IP_Port source, uint8_t *packet 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; + int index = -1; 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)); + index = add_to_entries(onion_a, source, packet + 1 + crypto_box_NONCEBYTES, + plain + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES, + packet + (ANNOUNCE_REQUEST_SIZE_RECV - ONION_RETURN_3)); } else { - stored = (in_entries(onion_a, plain + ONION_PING_ID_SIZE) != -1); + index = in_entries(onion_a, plain + ONION_PING_ID_SIZE); } /*Respond with a announce response packet*/ @@ -245,24 +255,29 @@ static int handle_announce_request(void *object, IP_Port source, uint8_t *packet uint8_t nonce[crypto_box_NONCEBYTES]; new_nonce(nonce); - uint8_t pl[ONION_PING_ID_SIZE + sizeof(nodes_list)] = {0}; + uint8_t pl[1 + ONION_PING_ID_SIZE + sizeof(nodes_list)]; - if (!stored) { - memcpy(pl, ping_id2, ONION_PING_ID_SIZE); + if (index == -1) { + pl[0] = 0; + memcpy(pl + 1, ping_id2, ONION_PING_ID_SIZE); + } else { + pl[0] = 1; + memcpy(pl + 1, onion_a->entries[index].data_public_key, crypto_box_PUBLICKEYBYTES); } - memcpy(pl + ONION_PING_ID_SIZE, nodes_list, num_nodes * sizeof(Node_format)); + memcpy(pl + 1 + ONION_PING_ID_SIZE, nodes_list, num_nodes * sizeof(Node_format)); uint8_t data[ONION_ANNOUNCE_RESPONSE_MAX_SIZE]; len = encrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion_a->dht->self_secret_key, nonce, pl, - ONION_PING_ID_SIZE + num_nodes * sizeof(Node_format), + 1 + ONION_PING_ID_SIZE + num_nodes * sizeof(Node_format), data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES); - if ((uint32_t)len != ONION_PING_ID_SIZE + num_nodes * sizeof(Node_format) + crypto_box_MACBYTES) + if ((uint32_t)len != 1 + ONION_PING_ID_SIZE + num_nodes * sizeof(Node_format) + crypto_box_MACBYTES) return 1; data[0] = NET_PACKET_ANNOUNCE_RESPONSE; - memcpy(data + 1, plain + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES, ONION_ANNOUNCE_SENDBACK_DATA_LENGTH); + memcpy(data + 1, plain + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES, + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH); memcpy(data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH, nonce, crypto_box_NONCEBYTES); if (send_onion_response(onion_a->net, source, data, @@ -321,6 +336,9 @@ Onion_Announce *new_onion_announce(DHT *dht) void kill_onion_announce(Onion_Announce *onion_a) { + if (onion_a == NULL) + return; + networking_registerhandler(onion_a->net, NET_PACKET_ANNOUNCE_REQUEST, NULL, NULL); networking_registerhandler(onion_a->net, NET_PACKET_ONION_DATA_REQUEST, NULL, NULL); free(onion_a); diff --git a/toxcore/onion_announce.h b/toxcore/onion_announce.h index 01cd7243..27b25bd4 100644 --- a/toxcore/onion_announce.h +++ b/toxcore/onion_announce.h @@ -31,15 +31,20 @@ #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 + 1 + 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_DATA_RESPONSE_MIN_SIZE (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES) +#if ONION_PING_ID_SIZE != crypto_box_PUBLICKEYBYTES +#error announce response packets assume that ONION_PING_ID_SIZE is equal to crypto_box_PUBLICKEYBYTES +#endif + typedef struct { uint8_t public_key[crypto_box_PUBLICKEYBYTES]; IP_Port ret_ip_port; uint8_t ret[ONION_RETURN_3]; + uint8_t data_public_key[crypto_box_PUBLICKEYBYTES]; uint64_t time; } Onion_Announce_Entry; @@ -59,6 +64,7 @@ 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. + * data_public_key is the public key we want others to encrypt their data packets with. * sendback_data is the data of ONION_ANNOUNCE_SENDBACK_DATA_LENGTH length that we expect to * receive back in the response. * @@ -66,7 +72,7 @@ typedef struct { * 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 *sendback_data); + uint8_t *client_id, uint8_t *data_public_key, uint8_t *sendback_data); /* Create and send an onion data request packet. * @@ -75,13 +81,15 @@ 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. + * encrypt_public_key is the public key used to encrypt the data packet. + * * 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 *nonce, uint8_t *data, - uint16_t length); +int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *encrypt_public_key, uint8_t *nonce, + uint8_t *data, uint16_t length); Onion_Announce *new_onion_announce(DHT *dht); diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index 27823f0d..32928fd9 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c @@ -30,7 +30,6 @@ #define ANNOUNCE_TIMEOUT 10 -static uint8_t zero_ping[ONION_PING_ID_SIZE]; /* Creates a sendback for use in an announce request. * @@ -107,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]; - if (new_sendback(onion_c, 0, dest_pubkey, dest, sendback) == -1) + if (new_sendback(onion_c, num, dest_pubkey, dest, sendback) == -1) return -1; uint8_t zero_ping_id[ONION_PING_ID_SIZE] = {0}; @@ -126,11 +125,11 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_ if (num == 0) { return send_announce_request(onion_c->dht, nodes, onion_c->dht->c->self_public_key, onion_c->dht->c->self_secret_key, ping_id, - onion_c->dht->c->self_public_key, sendback); + onion_c->dht->c->self_public_key, onion_c->temp_public_key, sendback); } else { return send_announce_request(onion_c->dht, nodes, onion_c->friends_list[num - 1].temp_public_key, onion_c->friends_list[num - 1].temp_secret_key, ping_id, - onion_c->friends_list[num - 1].real_client_id, sendback); + onion_c->friends_list[num - 1].real_client_id, zero_ping_id, sendback); } } @@ -164,7 +163,7 @@ static int cmp_entry(const void *a, const void *b) } 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) + uint8_t is_stored, uint8_t *pingid_or_key) { if (num > onion_c->num_friends) return -1; @@ -204,7 +203,14 @@ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, uint8_t *publ 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); + + if (is_stored) { + memcpy(list_nodes[index].data_public_key, pingid_or_key, crypto_box_PUBLICKEYBYTES); + } else { + memcpy(list_nodes[index].ping_id, pingid_or_key, ONION_PING_ID_SIZE); + } + + list_nodes[index].is_stored = is_stored; list_nodes[index].timestamp = unix_time(); list_nodes[index].last_pinged = 0; return 0; @@ -230,7 +236,7 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, Node_format *n reference_id = onion_c->friends_list[num - 1].real_client_id; } - uint32_t i; + uint32_t i, j; int lan_ips_accepted = (LAN_ip(source.ip) == 0); for (i = 0; i < num_nodes; ++i) { @@ -242,7 +248,15 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, Node_format *n if (is_timeout(list_nodes[0].timestamp, ONION_NODE_TIMEOUT) || 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); + /* check if node is already in list. */ + for (j = 0; j < MAX_ONION_CLIENTS; ++j) { + if (memcmp(list_nodes[j].client_id, nodes[i].client_id, crypto_box_PUBLICKEYBYTES) == 0) { + break; + } + } + + if (j == MAX_ONION_CLIENTS) + client_send_announce_request(onion_c, num, nodes[i].ip_port, nodes[i].client_id, NULL); } } @@ -268,7 +282,7 @@ static int handle_announce_response(void *object, IP_Port source, uint8_t *packe if (num > onion_c->num_friends) return 1; - uint8_t plain[ONION_PING_ID_SIZE + num_nodes * sizeof(Node_format)]; + uint8_t plain[1 + ONION_PING_ID_SIZE + num_nodes * sizeof(Node_format)]; int len = -1; if (num == 0) { @@ -289,10 +303,10 @@ static int handle_announce_response(void *object, IP_Port source, uint8_t *packe return 1; - if (client_add_to_list(onion_c, num, public_key, ip_port, plain) == -1) + if (client_add_to_list(onion_c, num, public_key, ip_port, plain[0], plain + 1) == -1) return 1; - if (client_ping_nodes(onion_c, num, (Node_format *)plain + ONION_PING_ID_SIZE, num_nodes, source) == -1) + if (client_ping_nodes(onion_c, num, (Node_format *)plain + 1 + ONION_PING_ID_SIZE, num_nodes, source) == -1) return 1; return 0; @@ -311,7 +325,7 @@ static int handle_data_response(void *object, IP_Port source, uint8_t *packet, u return 1; 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, + int len = decrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion_c->temp_secret_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES), temp_plain); @@ -333,7 +347,7 @@ static int handle_data_response(void *object, IP_Port source, uint8_t *packet, u } #define FAKEID_DATA_ID 156 -#define FAKEID_DATA_MIN_LENGTH (1 + crypto_box_PUBLICKEYBYTES) +#define FAKEID_DATA_MIN_LENGTH (1 + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES) #define FAKEID_DATA_MAX_LENGTH (FAKEID_DATA_MIN_LENGTH + sizeof(Node_format)*MAX_SENT_NODES) static int handle_fakeid_announce(void *object, uint8_t *source_pubkey, uint8_t *data, uint32_t length) { @@ -353,19 +367,30 @@ static int handle_fakeid_announce(void *object, uint8_t *source_pubkey, uint8_t if (friend_num == -1) return 1; - if (memcmp(data + 1, onion_c->friends_list[friend_num].fake_client_id, crypto_box_PUBLICKEYBYTES) != 0) { + uint64_t no_replay; + net_to_host(data + 1, sizeof(no_replay)); + memcpy(&no_replay, data + 1, sizeof(uint64_t)); + + if (no_replay <= onion_c->friends_list[friend_num].last_noreplay) + return 1; + + onion_c->friends_list[friend_num].last_noreplay = no_replay; + + if (memcmp(data + 1 + sizeof(uint64_t), onion_c->friends_list[friend_num].fake_client_id, + crypto_box_PUBLICKEYBYTES) != 0) { DHT_delfriend(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id); - if (DHT_addfriend(onion_c->dht, data + 1) == 1) { + if (DHT_addfriend(onion_c->dht, data + 1 + sizeof(uint64_t)) == 1) { return 1; } - memcpy(onion_c->friends_list[friend_num].fake_client_id, data + 1, crypto_box_PUBLICKEYBYTES); + onion_c->friends_list[friend_num].is_fake_clientid = 1; + memcpy(onion_c->friends_list[friend_num].fake_client_id, data + 1 + sizeof(uint64_t), crypto_box_PUBLICKEYBYTES); } uint16_t num_nodes = (length - FAKEID_DATA_MIN_LENGTH) / sizeof(Node_format); Node_format nodes[num_nodes]; - memcpy(nodes, data + 1 + crypto_box_PUBLICKEYBYTES, sizeof(nodes)); + memcpy(nodes, data + 1 + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES, sizeof(nodes)); uint32_t i; for (i = 0; i < num_nodes; ++i) { @@ -373,7 +398,6 @@ static int handle_fakeid_announce(void *object, uint8_t *source_pubkey, uint8_t DHT_getnodes(onion_c->dht, &nodes[i].ip_port, nodes[i].client_id, onion_c->friends_list[friend_num].fake_client_id); } - //TODO replay protection return 0; } /* Send data of length length to friendnum. @@ -413,7 +437,7 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, uint8_t *data, uint32 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) { + if (list_nodes[i].is_stored) { Node_format nodes[4]; if (random_path(onion_c, nodes) == -1) @@ -422,8 +446,8 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, uint8_t *data, uint32 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) + if (send_data_request(onion_c->dht, nodes, onion_c->friends_list[friend_num].real_client_id, + list_nodes[i].data_public_key, nonce, packet, sizeof(packet)) == 0) ++good; } } @@ -431,24 +455,104 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, uint8_t *data, uint32 return good; } -/* Send the packets to tell our friends +/* Try to send the fakeid via the DHT instead of onion + * + * Even if this function succeeds, the friend might not recieve any data. + * * return the number of packets sent on success * return -1 on failure. */ -static int send_fakeid_announce(Onion_Client *onion_c, uint16_t friend_num) +static int send_dht_fakeid(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 (!onion_c->friends_list[friend_num].is_fake_clientid) + return -1; + + uint8_t nonce[crypto_box_NONCEBYTES]; + new_nonce(nonce); + + uint8_t temp[DATA_IN_RESPONSE_MIN_SIZE + crypto_box_NONCEBYTES + length]; + memcpy(temp, onion_c->dht->c->self_public_key, crypto_box_PUBLICKEYBYTES); + memcpy(temp + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES); + int len = encrypt_data(onion_c->friends_list[friend_num].real_client_id, onion_c->dht->c->self_secret_key, nonce, data, + length, temp + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES); + + if ((uint32_t)len + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES != sizeof(temp)) + return -1; + + uint8_t packet[MAX_DATA_SIZE]; + len = create_request(onion_c->dht->self_public_key, onion_c->dht->self_secret_key, packet, + onion_c->friends_list[friend_num].fake_client_id, temp, sizeof(temp), FAKEID_DATA_ID); + + if (len == -1) + return -1; + + return route_tofriend(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id, packet, len); +} + +static int handle_dht_fakeid(void *object, IP_Port source, uint8_t *source_pubkey, uint8_t *packet, uint32_t length) +{ + Onion_Client *onion_c = object; + + if (length < FAKEID_DATA_MIN_LENGTH + DATA_IN_RESPONSE_MIN_SIZE + crypto_box_NONCEBYTES) + return 1; + + if (length > FAKEID_DATA_MAX_LENGTH + DATA_IN_RESPONSE_MIN_SIZE + crypto_box_NONCEBYTES) + return 1; + + uint8_t plain[FAKEID_DATA_MAX_LENGTH]; + int len = decrypt_data(packet, onion_c->dht->c->self_secret_key, packet + crypto_box_PUBLICKEYBYTES, + packet + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, + length - (crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES), plain); + + if ((uint32_t)len != length - (DATA_IN_RESPONSE_MIN_SIZE + crypto_box_NONCEBYTES)) + return 1; + + if (memcpy(source_pubkey, packet, crypto_box_PUBLICKEYBYTES) != 0) + return 1; + + return handle_fakeid_announce(onion_c, packet, plain, len); +} +/* Send the packets to tell our friends what our DHT public key is. + * + * if onion_dht_both is 0, use only the onion to send the packet. + * if it is 1, use only the dht. + * if it is something else, use both. + * + * return the number of packets sent on success + * return -1 on failure. + */ +static int send_fakeid_announce(Onion_Client *onion_c, uint16_t friend_num, uint8_t onion_dht_both) { if (friend_num >= onion_c->num_friends) return -1; uint8_t data[FAKEID_DATA_MAX_LENGTH]; data[0] = FAKEID_DATA_ID; - memcpy(data + 1, onion_c->dht->self_public_key, crypto_box_PUBLICKEYBYTES); + uint64_t no_replay = unix_time(); + host_to_net((uint8_t *)&no_replay, sizeof(no_replay)); + memcpy(data + 1, &no_replay, sizeof(no_replay)); + memcpy(data + 1 + sizeof(uint64_t), onion_c->dht->self_public_key, crypto_box_PUBLICKEYBYTES); Node_format nodes[MAX_SENT_NODES]; uint16_t num_nodes = closelist_nodes(onion_c->dht, nodes, MAX_SENT_NODES); memcpy(data + FAKEID_DATA_MIN_LENGTH, nodes, sizeof(Node_format) * num_nodes); - return send_onion_data(onion_c, friend_num, data, FAKEID_DATA_MIN_LENGTH + sizeof(Node_format) * num_nodes); - //TODO: somehow make this function send our DHT client id directly to the other if we know theirs but they don't - //seem to know ours. + int num1 = -1, num2 = -1; + + if (onion_dht_both != 1) + num1 = send_onion_data(onion_c, friend_num, data, FAKEID_DATA_MIN_LENGTH + sizeof(Node_format) * num_nodes); + + if (onion_dht_both != 0) + num2 = send_dht_fakeid(onion_c, friend_num, data, FAKEID_DATA_MIN_LENGTH + sizeof(Node_format) * num_nodes); + + if (num1 == -1) + return num2; + + if (num2 == -1) + return num1; + + return num1 + num2; } /* Get the friend_num of a friend. @@ -525,6 +629,7 @@ int onion_addfriend(Onion_Client *onion_c, uint8_t *client_id) onion_c->friends_list[index].status = 1; memcpy(onion_c->friends_list[index].real_client_id, client_id, crypto_box_PUBLICKEYBYTES); + crypto_box_keypair(onion_c->friends_list[index].temp_public_key, onion_c->friends_list[index].temp_secret_key); return index; } @@ -538,7 +643,9 @@ int onion_delfriend(Onion_Client *onion_c, int friend_num) if ((uint32_t)friend_num >= onion_c->num_friends) return -1; - DHT_delfriend(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id); + if (onion_c->friends_list[friend_num].is_fake_clientid) + DHT_delfriend(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id); + memset(&(onion_c->friends_list[friend_num]), 0, sizeof(Onion_Friend)); uint32_t i; @@ -557,8 +664,9 @@ int onion_delfriend(Onion_Client *onion_c, int friend_num) /* Get the ip of friend friendnum and put it in ip_port * - * return -1 on failure - * return 0 on success + * return -1, -- if client_id does NOT refer to a friend + * return 0, -- if client_id refers to a friend and we failed to find the friend (yet) + * return 1, ip if client_id refers to a friend and we found him * */ int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port) @@ -569,10 +677,31 @@ int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port) if (onion_c->friends_list[friend_num].status == 0) return -1; - if (DHT_getfriendip(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id, ip_port) == 1) - return 0; + if (!onion_c->friends_list[friend_num].is_fake_clientid) + return -1; - return -1; + return DHT_getfriendip(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id, ip_port); +} + +/* Set if friend is online or not. + * NOTE: This function is there and should be used so that we don't send useless packets to the friend if he is online. + * + * is_online 1 means friend is online. + * is_online 0 means friend is offline + * + * return -1 on failure. + * return 0 on success. + */ +int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_online) +{ + if ((uint32_t)friend_num >= onion_c->num_friends) + return -1; + + onion_c->friends_list[friend_num].is_online = is_online; + /* Should we reset the no_replay when the other goes offline? + if (!is_online) + onion_c->friends_list[friend_num].last_noreplay = 0; */ + return 0; } /* Takes 3 random nodes that we know and puts them in nodes @@ -591,7 +720,7 @@ int random_path(Onion_Client *onion_c, Node_format *nodes) return 0; } -#define ANNOUNCE_FRIEND 30 +#define ANNOUNCE_FRIEND 120 static void do_friend(Onion_Client *onion_c, uint16_t friendnum) { @@ -604,32 +733,39 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum) uint32_t i, count = 0; Onion_Node *list_nodes = onion_c->friends_list[friendnum].clients_list; - for (i = 0; i < MAX_ONION_CLIENTS; ++i) { - if (is_timeout(list_nodes[i].timestamp, ONION_NODE_TIMEOUT)) - continue; + if (!onion_c->friends_list[friendnum].is_online) { + for (i = 0; i < MAX_ONION_CLIENTS; ++i) { + if (is_timeout(list_nodes[i].timestamp, ONION_NODE_TIMEOUT)) + continue; - ++count; + ++count; - if (is_timeout(list_nodes[i].last_pinged, ANNOUNCE_FRIEND)) { - if (client_send_announce_request(onion_c, friendnum + 1, list_nodes[i].ip_port, list_nodes[i].client_id, 0) == 0) { - list_nodes[i].last_pinged = unix_time(); + if (is_timeout(list_nodes[i].last_pinged, ANNOUNCE_FRIEND)) { + if (client_send_announce_request(onion_c, friendnum + 1, list_nodes[i].ip_port, list_nodes[i].client_id, 0) == 0) { + list_nodes[i].last_pinged = unix_time(); + } } } + + if (count < MAX_ONION_CLIENTS / 2) { + Node_format nodes_list[MAX_SENT_NODES]; + uint32_t num_nodes = get_close_nodes(onion_c->dht, onion_c->friends_list[friendnum].real_client_id, nodes_list, + rand() % 2 ? AF_INET : AF_INET6, 1, 0); + + for (i = 0; i < num_nodes; ++i) + client_send_announce_request(onion_c, friendnum + 1, nodes_list[i].ip_port, nodes_list[i].client_id, 0); + } + + + /* send packets to friend telling them our fake DHT id. */ + if (is_timeout(onion_c->friends_list[friendnum].last_fakeid_onion_sent, ONION_FAKEID_INTERVAL)) + if (send_fakeid_announce(onion_c, friendnum, 0) > 1) + onion_c->friends_list[friendnum].last_fakeid_onion_sent = unix_time(); + + if (is_timeout(onion_c->friends_list[friendnum].last_fakeid_dht_sent, DHT_FAKEID_INTERVAL)) + if (send_fakeid_announce(onion_c, friendnum, 1) > 1) + onion_c->friends_list[friendnum].last_fakeid_dht_sent = unix_time(); } - - if (count < MAX_ONION_CLIENTS / 2) { - Node_format nodes_list[MAX_SENT_NODES]; - uint32_t num_nodes = get_close_nodes(onion_c->dht, onion_c->friends_list[i].real_client_id, nodes_list, - rand() % 2 ? AF_INET : AF_INET6, rand() % 2, 1); - - for (i = 0; i < num_nodes; ++i) - client_send_announce_request(onion_c, friendnum + 1, nodes_list[i].ip_port, nodes_list[i].client_id, 0); - } - - /* send packets to friend telling them our fake DHT id. */ - if (is_timeout(onion_c->friends_list[friendnum].last_fakeid_sent, ONION_FAKEID_INTERVAL)) - if (send_fakeid_announce(onion_c, friendnum) > 3) - onion_c->friends_list[friendnum].last_fakeid_sent = unix_time(); } /* 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) @@ -639,7 +775,7 @@ void oniondata_registerhandler(Onion_Client *onion_c, uint8_t byte, oniondata_ha } #define ANNOUNCE_INTERVAL_NOT_ANNOUNCED 10 -#define ANNOUNCE_INTERVAL_ANNOUNCED 60 +#define ANNOUNCE_INTERVAL_ANNOUNCED 120 static void do_announce(Onion_Client *onion_c) { @@ -653,7 +789,7 @@ static void do_announce(Onion_Client *onion_c) ++count; uint32_t interval = ANNOUNCE_INTERVAL_NOT_ANNOUNCED; - if (memcmp(list_nodes[i].ping_id, zero_ping, ONION_PING_ID_SIZE) == 0) { + if (list_nodes[i].is_stored) { interval = ANNOUNCE_INTERVAL_ANNOUNCED; } @@ -668,7 +804,7 @@ static void do_announce(Onion_Client *onion_c) if (count < MAX_ONION_CLIENTS / 2) { Node_format nodes_list[MAX_SENT_NODES]; uint32_t num_nodes = get_close_nodes(onion_c->dht, onion_c->dht->c->self_public_key, nodes_list, - rand() % 2 ? AF_INET : AF_INET6, rand() % 2, 1); + rand() % 2 ? AF_INET : AF_INET6, 1, 0); for (i = 0; i < num_nodes; ++i) client_send_announce_request(onion_c, 0, nodes_list[i].ip_port, nodes_list[i].client_id, 0); @@ -704,16 +840,20 @@ Onion_Client *new_onion_client(DHT *dht) onion_c->dht = dht; onion_c->net = dht->c->lossless_udp->net; new_symmetric_key(onion_c->secret_symmetric_key); - + crypto_box_keypair(onion_c->temp_public_key, onion_c->temp_secret_key); networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, &handle_announce_response, onion_c); networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, &handle_data_response, onion_c); oniondata_registerhandler(onion_c, FAKEID_DATA_ID, &handle_fakeid_announce, onion_c); + cryptopacket_registerhandler(onion_c->dht->c, FAKEID_DATA_ID, &handle_dht_fakeid, onion_c); return onion_c; } void kill_onion_client(Onion_Client *onion_c) { + if (onion_c == NULL) + return; + networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, NULL, NULL); networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, NULL, NULL); free(onion_c); diff --git a/toxcore/onion_client.h b/toxcore/onion_client.h index 181bc533..9491b0b7 100644 --- a/toxcore/onion_client.h +++ b/toxcore/onion_client.h @@ -27,15 +27,19 @@ #include "onion_announce.h" #define MAX_ONION_CLIENTS 8 -#define ONION_NODE_TIMEOUT 200 +#define ONION_NODE_TIMEOUT 240 /* The interval in seconds at which to tell our friends where we are */ #define ONION_FAKEID_INTERVAL 60 +#define DHT_FAKEID_INTERVAL 20 typedef struct { uint8_t client_id[CLIENT_ID_SIZE]; IP_Port ip_port; uint8_t ping_id[ONION_PING_ID_SIZE]; + uint8_t data_public_key[crypto_box_PUBLICKEYBYTES]; + uint8_t is_stored; + uint64_t timestamp; uint64_t last_pinged; @@ -43,7 +47,9 @@ typedef struct { typedef struct { uint8_t status; /* 0 if friend is not valid, 1 if friend is valid.*/ + uint8_t is_online; /* Set by the onion_set_friend_status function. */ + uint8_t is_fake_clientid; /* 0 if we don't know the fake client id of the other 1 if we do. */ uint8_t fake_client_id[crypto_box_PUBLICKEYBYTES]; uint8_t real_client_id[crypto_box_PUBLICKEYBYTES]; @@ -51,7 +57,10 @@ typedef struct { uint8_t temp_public_key[crypto_box_PUBLICKEYBYTES]; uint8_t temp_secret_key[crypto_box_SECRETKEYBYTES]; - uint64_t last_fakeid_sent; + uint64_t last_fakeid_onion_sent; + uint64_t last_fakeid_dht_sent; + + uint64_t last_noreplay; } Onion_Friend; typedef int (*oniondata_handler_callback)(void *object, uint8_t *source_pubkey, uint8_t *data, uint32_t len); @@ -67,6 +76,8 @@ typedef struct { uint8_t secret_symmetric_key[crypto_secretbox_KEYBYTES]; uint64_t last_run; + uint8_t temp_public_key[crypto_box_PUBLICKEYBYTES]; + uint8_t temp_secret_key[crypto_box_SECRETKEYBYTES]; struct { oniondata_handler_callback function; void *object; @@ -94,10 +105,22 @@ int onion_addfriend(Onion_Client *onion_c, uint8_t *client_id); */ int onion_delfriend(Onion_Client *onion_c, int friend_num); +/* Set if friend is online or not. + * NOTE: This function is there and should be used so that we don't send useless packets to the friend if he is online. + * + * is_online 1 means friend is online. + * is_online 0 means friend is offline + * + * return -1 on failure. + * return 0 on success. + */ +int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_online); + /* Get the ip of friend friendnum and put it in ip_port * - * return -1 on failure - * return 0 on success + * return -1, -- if client_id does NOT refer to a friend + * return 0, -- if client_id refers to a friend and we failed to find the friend (yet) + * return 1, ip if client_id refers to a friend and we found him * */ int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port); diff --git a/toxcore/ping.c b/toxcore/ping.c index 6c368d0c..a37b531d 100644 --- a/toxcore/ping.c +++ b/toxcore/ping.c @@ -47,7 +47,7 @@ typedef struct { } pinged_t; struct PING { - Net_Crypto *c; + DHT *dht; pinged_t pings[PING_NUM_MAX]; size_t num_pings; @@ -148,19 +148,19 @@ int send_ping_request(PING *ping, IP_Port ipp, uint8_t *client_id) int rc; uint64_t ping_id; - if (is_pinging(ping, ipp, 0) || id_equal(client_id, ping->c->self_public_key)) + if (is_pinging(ping, ipp, 0) || id_equal(client_id, ping->dht->self_public_key)) return 1; // Generate random ping_id. ping_id = add_ping(ping, ipp); pk[0] = NET_PACKET_PING_REQUEST; - id_copy(pk + 1, ping->c->self_public_key); // Our pubkey + id_copy(pk + 1, ping->dht->self_public_key); // Our pubkey new_nonce(pk + 1 + CLIENT_ID_SIZE); // Generate new nonce // Encrypt ping_id using recipient privkey rc = encrypt_data(client_id, - ping->c->self_secret_key, + ping->dht->self_secret_key, pk + 1 + CLIENT_ID_SIZE, (uint8_t *) &ping_id, sizeof(ping_id), pk + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES); @@ -168,7 +168,7 @@ int send_ping_request(PING *ping, IP_Port ipp, uint8_t *client_id) if (rc != sizeof(ping_id) + crypto_box_MACBYTES) return 1; - return sendpacket(ping->c->lossless_udp->net, ipp, pk, sizeof(pk)); + return sendpacket(ping->dht->net, ipp, pk, sizeof(pk)); } static int send_ping_response(PING *ping, IP_Port ipp, uint8_t *client_id, uint64_t ping_id) @@ -176,16 +176,16 @@ static int send_ping_response(PING *ping, IP_Port ipp, uint8_t *client_id, uint6 uint8_t pk[DHT_PING_SIZE]; int rc; - if (id_equal(client_id, ping->c->self_public_key)) + if (id_equal(client_id, ping->dht->self_public_key)) return 1; pk[0] = NET_PACKET_PING_RESPONSE; - id_copy(pk + 1, ping->c->self_public_key); // Our pubkey + id_copy(pk + 1, ping->dht->self_public_key); // Our pubkey new_nonce(pk + 1 + CLIENT_ID_SIZE); // Generate new nonce // Encrypt ping_id using recipient privkey rc = encrypt_data(client_id, - ping->c->self_secret_key, + ping->dht->self_secret_key, pk + 1 + CLIENT_ID_SIZE, (uint8_t *) &ping_id, sizeof(ping_id), pk + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES); @@ -193,7 +193,7 @@ static int send_ping_response(PING *ping, IP_Port ipp, uint8_t *client_id, uint6 if (rc != sizeof(ping_id) + crypto_box_MACBYTES) return 1; - return sendpacket(ping->c->lossless_udp->net, ipp, pk, sizeof(pk)); + return sendpacket(ping->dht->net, ipp, pk, sizeof(pk)); } static int handle_ping_request(void *_dht, IP_Port source, uint8_t *packet, uint32_t length) @@ -207,12 +207,12 @@ static int handle_ping_request(void *_dht, IP_Port source, uint8_t *packet, uint PING *ping = dht->ping; - if (id_equal(packet + 1, ping->c->self_public_key)) + if (id_equal(packet + 1, ping->dht->self_public_key)) return 1; // Decrypt ping_id rc = decrypt_data(packet + 1, - ping->c->self_secret_key, + ping->dht->self_secret_key, packet + 1 + CLIENT_ID_SIZE, packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, sizeof(ping_id) + crypto_box_MACBYTES, @@ -239,12 +239,12 @@ static int handle_ping_response(void *_dht, IP_Port source, uint8_t *packet, uin PING *ping = dht->ping; - if (id_equal(packet + 1, ping->c->self_public_key)) + if (id_equal(packet + 1, ping->dht->self_public_key)) return 1; // Decrypt ping_id rc = decrypt_data(packet + 1, - ping->c->self_secret_key, + ping->dht->self_secret_key, packet + 1 + CLIENT_ID_SIZE, packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, sizeof(ping_id) + crypto_box_MACBYTES, @@ -291,7 +291,7 @@ int add_toping(PING *ping, uint8_t *client_id, IP_Port ip_port) } for (i = 0; i < MAX_TOPING; ++i) { - if (id_closest(ping->c->self_public_key, ping->toping[i].client_id, client_id) == 2) { + if (id_closest(ping->dht->self_public_key, ping->toping[i].client_id, client_id) == 2) { memcpy(ping->toping[i].client_id, client_id, CLIENT_ID_SIZE); ipport_copy(&ping->toping[i].ip_port, &ip_port); return 0; @@ -323,24 +323,24 @@ void do_toping(PING *ping) } -PING *new_ping(DHT *dht, Net_Crypto *c) +PING *new_ping(DHT *dht) { PING *ping = calloc(1, sizeof(PING)); if (ping == NULL) return NULL; - ping->c = c; - networking_registerhandler(ping->c->lossless_udp->net, NET_PACKET_PING_REQUEST, &handle_ping_request, dht); - networking_registerhandler(ping->c->lossless_udp->net, NET_PACKET_PING_RESPONSE, &handle_ping_response, dht); + ping->dht = dht; + networking_registerhandler(ping->dht->net, NET_PACKET_PING_REQUEST, &handle_ping_request, dht); + networking_registerhandler(ping->dht->net, NET_PACKET_PING_RESPONSE, &handle_ping_response, dht); return ping; } void kill_ping(PING *ping) { - networking_registerhandler(ping->c->lossless_udp->net, NET_PACKET_PING_REQUEST, NULL, NULL); - networking_registerhandler(ping->c->lossless_udp->net, NET_PACKET_PING_RESPONSE, NULL, NULL); + networking_registerhandler(ping->dht->net, NET_PACKET_PING_REQUEST, NULL, NULL); + networking_registerhandler(ping->dht->net, NET_PACKET_PING_RESPONSE, NULL, NULL); free(ping); } diff --git a/toxcore/ping.h b/toxcore/ping.h index 00e1c697..a0008f3c 100644 --- a/toxcore/ping.h +++ b/toxcore/ping.h @@ -39,7 +39,7 @@ typedef struct PING PING; int add_toping(PING *ping, uint8_t *client_id, IP_Port ip_port); void do_toping(PING *ping); -PING *new_ping(DHT *dht, Net_Crypto *c); +PING *new_ping(DHT *dht); void kill_ping(PING *ping); int send_ping_request(PING *ping, IP_Port ipp, uint8_t *client_id); diff --git a/toxcore/util.c b/toxcore/util.c index 9af7262f..d56c446e 100644 --- a/toxcore/util.c +++ b/toxcore/util.c @@ -65,6 +65,25 @@ uint32_t id_copy(uint8_t *dest, uint8_t *src) return CLIENT_ID_SIZE; } +void host_to_net(uint8_t *num, uint16_t numbytes) +{ + union { + uint32_t i; + uint8_t c[4]; + } a; + a.i = 1; + + if (a.c[0] == 1) { + uint32_t i; + uint8_t buff[numbytes]; + + for (i = 0; i < numbytes; ++i) { + buff[i] = num[numbytes - i - 1]; + } + + memcpy(num, buff, numbytes); + } +} /* state load/save */ int load_state(load_state_callback_func load_state_callback, void *outer, diff --git a/toxcore/util.h b/toxcore/util.h index f05a9821..ae364d52 100644 --- a/toxcore/util.h +++ b/toxcore/util.h @@ -37,6 +37,8 @@ int is_timeout(uint64_t timestamp, uint64_t timeout); bool id_equal(uint8_t *dest, uint8_t *src); uint32_t id_copy(uint8_t *dest, uint8_t *src); /* return value is CLIENT_ID_SIZE */ +void host_to_net(uint8_t *num, uint16_t numbytes); +#define net_to_host(x, y) host_to_net(x, y) /* state load/save */ typedef int (*load_state_callback_func)(void *outer, uint8_t *data, uint32_t len, uint16_t type);