From 881e95671ac7bf8b9191e2b6391ed3d143fae3b3 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 11 Apr 2014 22:09:04 -0400 Subject: [PATCH 001/117] Some code written for the TCP part. --- toxcore/TCP_client.c | 142 ++++++++++++++++++++++++++++++++++++++++++- toxcore/TCP_server.c | 29 +++++---- toxcore/TCP_server.h | 8 +++ 3 files changed, 165 insertions(+), 14 deletions(-) diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c index 437429b9..496f48d7 100644 --- a/toxcore/TCP_client.c +++ b/toxcore/TCP_client.c @@ -130,6 +130,103 @@ static int send_pending_data(TCP_Client_Connection *con) return -1; } +/* return 1 on success. + * return 0 if could not send packet. + * return -1 on failure (connection must be killed). + */ +static int write_packet_TCP_secure_connection(TCP_Client_Connection *con, uint8_t *data, uint16_t length) +{ + if (length + crypto_box_MACBYTES > MAX_PACKET_SIZE) + return -1; + + if (send_pending_data(con) == -1) + return 0; + + uint8_t packet[sizeof(uint16_t) + length + crypto_box_MACBYTES]; + + uint16_t c_length = htons(length + crypto_box_MACBYTES); + memcpy(packet, &c_length, sizeof(uint16_t)); + int len = encrypt_data_fast(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t)); + + if ((unsigned int)len != (sizeof(packet) - sizeof(uint16_t))) + return -1; + + increment_nonce(con->sent_nonce); + + len = send(con->sock, packet, sizeof(packet), MSG_NOSIGNAL); + + if ((unsigned int)len == sizeof(packet)) + return 1; + + if (len <= 0) + return 0; + + memcpy(con->last_packet, packet, length); + con->last_packet_length = sizeof(packet); + con->last_packet_sent = len; + return 1; +} + +/* return 1 on success. + * return 0 if could not send packet. + * return -1 on failure (connection must be killed). + */ +static int send_routing_request(TCP_Client_Connection *con, uint8_t *public_key) +{ + uint8_t packet[1 + crypto_box_PUBLICKEYBYTES]; + packet[0] = TCP_PACKET_ROUTING_REQUEST; + memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES); + return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); +} + +/* return 1 on success. + * return 0 if could not send packet. + * return -1 on failure (connection must be killed). + */ +static int send_disconnect_notification(TCP_Client_Connection *con, uint8_t id) +{ + uint8_t packet[1 + 1]; + packet[0] = TCP_PACKET_DISCONNECT_NOTIFICATION; + packet[1] = id; + return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); +} + +/* return 1 on success. + * return 0 if could not send packet. + * return -1 on failure (connection must be killed). + */ +static int send_ping_request(TCP_Client_Connection *con, uint64_t ping_id) +{ + uint8_t packet[1 + sizeof(uint64_t)]; + packet[0] = TCP_PACKET_PING; + memcpy(packet + 1, &ping_id, sizeof(uint64_t)); + return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); +} + +/* return 1 on success. + * return 0 if could not send packet. + * return -1 on failure (connection must be killed). + */ +static int send_ping_response(TCP_Client_Connection *con, uint64_t ping_id) +{ + uint8_t packet[1 + sizeof(uint64_t)]; + packet[0] = TCP_PACKET_PONG; + memcpy(packet + 1, &ping_id, sizeof(uint64_t)); + return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); +} + +/* return 1 on success. + * return 0 if could not send packet. + * return -1 on failure (connection must be killed). + */ +static int send_onion_request(TCP_Client_Connection *con, uint8_t *data, uint16_t length) +{ + uint8_t packet[1 + length]; + packet[0] = TCP_PACKET_ONION_REQUEST; + memcpy(packet + 1, data, length); + return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); +} + /* Create new TCP connection to ip_port/public_key */ TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, uint8_t *public_key, uint8_t *self_public_key, @@ -176,8 +273,51 @@ TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, uint8_t *public_key, return temp; } -static int do_confirmed_TCP(TCP_Client_Connection *TCP_connection) +/* return 0 on success + * return -1 on failure + */ +static int handle_TCP_packet(TCP_Client_Connection *conn, uint8_t *data, uint16_t length) { + if (length == 0) + return -1; + + switch (data[0]) { + case TCP_PACKET_PING: { + if (length != 1 + sizeof(uint64_t)) + return -1; + + uint64_t ping_id; + memcpy(&ping_id, data + 1, sizeof(uint64_t)); + send_ping_response(conn, ping_id); + return 0; + } + + default: { + + } + } + + return 0; +} + +static int do_confirmed_TCP(TCP_Client_Connection *conn) +{ + send_pending_data(conn); + uint8_t packet[MAX_PACKET_SIZE]; + int len; + + while ((len = read_packet_TCP_secure_connection(conn->sock, &conn->next_packet_length, conn->shared_key, + conn->recv_nonce, packet, sizeof(packet)))) { + if (len == -1) { + conn->status = TCP_CLIENT_DISCONNECTED; + break; + } + + if (handle_TCP_packet(conn, packet, len) == -1) { + conn->status = TCP_CLIENT_DISCONNECTED; + break; + } + } return 0; } diff --git a/toxcore/TCP_server.c b/toxcore/TCP_server.c index 4eed1209..847f04e7 100644 --- a/toxcore/TCP_server.c +++ b/toxcore/TCP_server.c @@ -228,10 +228,11 @@ int read_TCP_packet(sock_t sock, uint8_t *data, uint16_t length) * return 0 if could not read any packet. * return -1 on failure (connection must be killed). */ -static int read_packet_TCP_secure_connection(TCP_Secure_Connection *con, uint8_t *data, uint16_t max_len) +int read_packet_TCP_secure_connection(sock_t sock, uint16_t *next_packet_length, uint8_t *shared_key, + uint8_t *recv_nonce, uint8_t *data, uint16_t max_len) { - if (con->next_packet_length == 0) { - uint16_t len = read_TCP_length(con->sock); + if (*next_packet_length == 0) { + uint16_t len = read_TCP_length(sock); if (len == (uint16_t)~0) return -1; @@ -239,26 +240,26 @@ static int read_packet_TCP_secure_connection(TCP_Secure_Connection *con, uint8_t if (len == 0) return 0; - con->next_packet_length = len; + *next_packet_length = len; } - if (max_len + crypto_box_MACBYTES < con->next_packet_length) + if (max_len + crypto_box_MACBYTES < *next_packet_length) return -1; - uint8_t data_encrypted[con->next_packet_length]; - int len_packet = read_TCP_packet(con->sock, data_encrypted, con->next_packet_length); + uint8_t data_encrypted[*next_packet_length]; + int len_packet = read_TCP_packet(sock, data_encrypted, *next_packet_length); - if (len_packet != con->next_packet_length) + if (len_packet != *next_packet_length) return 0; - con->next_packet_length = 0; + *next_packet_length = 0; - int len = decrypt_data_fast(con->shared_key, con->recv_nonce, data_encrypted, len_packet, data); + int len = decrypt_data_fast(shared_key, recv_nonce, data_encrypted, len_packet, data); if (len + crypto_box_MACBYTES != len_packet) return -1; - increment_nonce(con->recv_nonce); + increment_nonce(recv_nonce); return len; } @@ -848,7 +849,8 @@ static void do_TCP_unconfirmed(TCP_Server *TCP_server) continue; uint8_t packet[MAX_PACKET_SIZE]; - int len = read_packet_TCP_secure_connection(conn, packet, sizeof(packet)); + int len = read_packet_TCP_secure_connection(conn->sock, &conn->next_packet_length, conn->shared_key, conn->recv_nonce, + packet, sizeof(packet)); if (len == 0) { continue; @@ -902,7 +904,8 @@ static void do_TCP_confirmed(TCP_Server *TCP_server) uint8_t packet[MAX_PACKET_SIZE]; int len; - while ((len = read_packet_TCP_secure_connection(conn, packet, sizeof(packet)))) { + while ((len = read_packet_TCP_secure_connection(conn->sock, &conn->next_packet_length, conn->shared_key, + conn->recv_nonce, packet, sizeof(packet)))) { if (len == -1) { kill_TCP_connection(conn); del_accepted(TCP_server, i); diff --git a/toxcore/TCP_server.h b/toxcore/TCP_server.h index 3ae0eba4..57313038 100644 --- a/toxcore/TCP_server.h +++ b/toxcore/TCP_server.h @@ -140,4 +140,12 @@ uint16_t read_TCP_length(sock_t sock); */ int read_TCP_packet(sock_t sock, uint8_t *data, uint16_t length); +/* return length of recieved packet on success. + * return 0 if could not read any packet. + * return -1 on failure (connection must be killed). + */ +int read_packet_TCP_secure_connection(sock_t sock, uint16_t *next_packet_length, uint8_t *shared_key, + uint8_t *recv_nonce, uint8_t *data, uint16_t max_len); + + #endif From 268172ec411d3b3717e6b4a5ef194e8ebf4b69bd Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 12 Apr 2014 22:00:46 -0400 Subject: [PATCH 002/117] Pings and onion packets implemented in TCP_Client.c Astyled one test and added a couple lines to another. --- auto_tests/TCP_test.c | 12 ++++++ auto_tests/toxav_basic_test.c | 12 +++--- toxcore/TCP_client.c | 69 ++++++++++++++++++++++++++++++++++- toxcore/TCP_client.h | 18 +++++++-- 4 files changed, 100 insertions(+), 11 deletions(-) diff --git a/auto_tests/TCP_test.c b/auto_tests/TCP_test.c index de37bb97..2ae1dc78 100644 --- a/auto_tests/TCP_test.c +++ b/auto_tests/TCP_test.c @@ -320,6 +320,18 @@ START_TEST(test_client) do_TCP_connection(conn); ck_assert_msg(conn->status == TCP_CLIENT_CONFIRMED, "Wrong status. Expected: %u, is: %u", TCP_CLIENT_CONFIRMED, conn->status); + c_sleep(500); + do_TCP_connection(conn); + ck_assert_msg(conn->status == TCP_CLIENT_CONFIRMED, "Wrong status. Expected: %u, is: %u", TCP_CLIENT_CONFIRMED, + conn->status); + c_sleep(500); + do_TCP_connection(conn); + ck_assert_msg(conn->status == TCP_CLIENT_CONFIRMED, "Wrong status. Expected: %u, is: %u", TCP_CLIENT_CONFIRMED, + conn->status); + do_TCP_server(tcp_s); + c_sleep(50); + ck_assert_msg(conn->status == TCP_CLIENT_CONFIRMED, "Wrong status. Expected: %u, is: %u", TCP_CLIENT_CONFIRMED, + conn->status); } END_TEST diff --git a/auto_tests/toxav_basic_test.c b/auto_tests/toxav_basic_test.c index f337217c..ea74f90b 100644 --- a/auto_tests/toxav_basic_test.c +++ b/auto_tests/toxav_basic_test.c @@ -296,8 +296,8 @@ START_TEST(test_AV) toxav_recv_video(status_control.Alice.av, &video_storage); if ( video_storage ) { - /*ck_assert_msg( memcmp(video_storage->planes[VPX_PLANE_Y], sample_payload, 10) == 0 || - memcmp(video_storage->planes[VPX_PLANE_U], sample_payload, 10) == 0 || + /*ck_assert_msg( memcmp(video_storage->planes[VPX_PLANE_Y], sample_payload, 10) == 0 || + memcmp(video_storage->planes[VPX_PLANE_U], sample_payload, 10) == 0 || memcmp(video_storage->planes[VPX_PLANE_V], sample_payload, 10) == 0 , "Payload from Bob is invalid");*/ } @@ -351,8 +351,8 @@ START_TEST(test_AV) toxav_recv_video(status_control.Alice.av, &video_storage); if ( video_storage ) { - /*ck_assert_msg( memcmp(video_storage->planes[VPX_PLANE_Y], sample_payload, 10) == 0 || - memcmp(video_storage->planes[VPX_PLANE_U], sample_payload, 10) == 0 || + /*ck_assert_msg( memcmp(video_storage->planes[VPX_PLANE_Y], sample_payload, 10) == 0 || + memcmp(video_storage->planes[VPX_PLANE_U], sample_payload, 10) == 0 || memcmp(video_storage->planes[VPX_PLANE_V], sample_payload, 10) == 0 , "Payload from Bob is invalid");*/ } @@ -370,8 +370,8 @@ START_TEST(test_AV) toxav_recv_video(status_control.Bob.av, &video_storage); if ( video_storage ) { - /*ck_assert_msg( memcmp(video_storage->planes[VPX_PLANE_Y], sample_payload, 10) == 0 || - memcmp(video_storage->planes[VPX_PLANE_U], sample_payload, 10) == 0 || + /*ck_assert_msg( memcmp(video_storage->planes[VPX_PLANE_Y], sample_payload, 10) == 0 || + memcmp(video_storage->planes[VPX_PLANE_U], sample_payload, 10) == 0 || memcmp(video_storage->planes[VPX_PLANE_V], sample_payload, 10) == 0 , "Payload from Alice is invalid");*/ } diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c index 496f48d7..9c6003ae 100644 --- a/toxcore/TCP_client.c +++ b/toxcore/TCP_client.c @@ -219,7 +219,7 @@ static int send_ping_response(TCP_Client_Connection *con, uint64_t ping_id) * return 0 if could not send packet. * return -1 on failure (connection must be killed). */ -static int send_onion_request(TCP_Client_Connection *con, uint8_t *data, uint16_t length) +int send_onion_request(TCP_Client_Connection *con, uint8_t *data, uint16_t length) { uint8_t packet[1 + length]; packet[0] = TCP_PACKET_ONION_REQUEST; @@ -227,6 +227,13 @@ static int send_onion_request(TCP_Client_Connection *con, uint8_t *data, uint16_ return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); } +void onion_response_handler(TCP_Client_Connection *con, int (*onion_callback)(void *object, uint8_t *data, + uint16_t length), void *object) +{ + con->onion_callback = onion_callback; + con->onion_callback_object = object; +} + /* Create new TCP connection to ip_port/public_key */ TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, uint8_t *public_key, uint8_t *self_public_key, @@ -282,6 +289,18 @@ static int handle_TCP_packet(TCP_Client_Connection *conn, uint8_t *data, uint16_ return -1; switch (data[0]) { + case TCP_PACKET_ROUTING_RESPONSE: { + return 0; + } + + case TCP_PACKET_CONNECTION_NOTIFICATION: { + return 0; + } + + case TCP_PACKET_DISCONNECT_NOTIFICATION: { + return 0; + } + case TCP_PACKET_PING: { if (length != 1 + sizeof(uint64_t)) return -1; @@ -292,8 +311,35 @@ static int handle_TCP_packet(TCP_Client_Connection *conn, uint8_t *data, uint16_ return 0; } - default: { + case TCP_PACKET_PONG: { + if (length != 1 + sizeof(uint64_t)) + return -1; + uint64_t ping_id; + memcpy(&ping_id, data + 1, sizeof(uint64_t)); + + if (ping_id) { + if (ping_id == conn->ping_id) { + conn->ping_id = 0; + } + + return 0; + } else { + return -1; + } + } + + case TCP_PACKET_ONION_RESPONSE: { + conn->onion_callback(conn->onion_callback_object, data + 1, length - 1); + return 0; + } + + default: { + if (data[0] < NUM_RESERVED_PORTS) + return -1; + + uint8_t con_id = data[0] - NUM_RESERVED_PORTS; + //TODO } } @@ -306,6 +352,25 @@ static int do_confirmed_TCP(TCP_Client_Connection *conn) uint8_t packet[MAX_PACKET_SIZE]; int len; + if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY)) { + uint64_t ping_id = random_64b(); + + if (!ping_id) + ++ping_id; + + int ret = send_ping_request(conn, ping_id); + + if (ret == 1) { + conn->last_pinged = unix_time(); + conn->ping_id = ping_id; + } + } + + if (conn->ping_id && is_timeout(conn->last_pinged, TCP_PING_TIMEOUT)) { + conn->status = TCP_CLIENT_DISCONNECTED; + return 0; + } + while ((len = read_packet_TCP_secure_connection(conn->sock, &conn->next_packet_length, conn->shared_key, conn->recv_nonce, packet, sizeof(packet)))) { if (len == -1) { diff --git a/toxcore/TCP_client.h b/toxcore/TCP_client.h index eb2aa39c..e096ae62 100644 --- a/toxcore/TCP_client.h +++ b/toxcore/TCP_client.h @@ -55,6 +55,14 @@ typedef struct { uint64_t last_pinged; uint64_t ping_id; + + struct { + uint8_t status; /* 0 if not used, 1 if other is offline, 2 if other is online. */ + uint8_t public_key[crypto_box_PUBLICKEYBYTES]; + } connections[NUM_CLIENT_CONNECTIONS]; + + int (*onion_callback)(void *object, uint8_t *data, uint16_t length); + void *onion_callback_object; } TCP_Client_Connection; /* Create new TCP connection to ip_port/public_key @@ -70,9 +78,13 @@ void do_TCP_connection(TCP_Client_Connection *TCP_connection); */ void kill_TCP_connection(TCP_Client_Connection *TCP_connection); -int get_TCP_connection_status(TCP_Client_Connection *TCP_connection); - -int read_TCP_connection(TCP_Client_Connection *TCP_connection, uint8_t *data); +/* return 1 on success. + * return 0 if could not send packet. + * return -1 on failure (connection must be killed). + */ +int send_onion_request(TCP_Client_Connection *con, uint8_t *data, uint16_t length); +void onion_response_handler(TCP_Client_Connection *con, int (*onion_callback)(void *object, uint8_t *data, + uint16_t length), void *object); #endif From ecf0ff3e7f4f5517ae1b66f01aec3325638f7761 Mon Sep 17 00:00:00 2001 From: Steven Noonan Date: Sun, 13 Apr 2014 04:01:38 -0700 Subject: [PATCH 003/117] sockets: support Mac OS X way of disabling SIGPIPE on a socket Mac OS X doesn't have MSG_NOSIGNAL, so we need to use SO_NOSIGPIPE. Signed-off-by: Steven Noonan --- toxcore/TCP_client.c | 7 ++++++- toxcore/TCP_server.c | 5 +++++ toxcore/TCP_server.h | 2 +- toxcore/network.c | 15 +++++++++++++++ toxcore/network.h | 7 +++++++ 5 files changed, 34 insertions(+), 2 deletions(-) diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c index 9c6003ae..18f63c5f 100644 --- a/toxcore/TCP_client.c +++ b/toxcore/TCP_client.c @@ -253,6 +253,11 @@ TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, uint8_t *public_key, return NULL; } + if (!set_socket_nosigpipe(sock)) { + kill_sock(sock); + return 0; + } + if (!(set_socket_nonblock(sock) && connect_sock_to(sock, ip_port))) { kill_sock(sock); return NULL; @@ -433,4 +438,4 @@ void kill_TCP_connection(TCP_Client_Connection *TCP_connection) kill_sock(TCP_connection->sock); memset(TCP_connection, 0, sizeof(TCP_Client_Connection)); free(TCP_connection); -} \ No newline at end of file +} diff --git a/toxcore/TCP_server.c b/toxcore/TCP_server.c index 847f04e7..410111f4 100644 --- a/toxcore/TCP_server.c +++ b/toxcore/TCP_server.c @@ -702,6 +702,11 @@ static int accept_connection(TCP_Server *TCP_server, sock_t sock) return 0; } + if (!set_socket_nosigpipe(sock)) { + kill_sock(sock); + return 0; + } + TCP_Secure_Connection *conn = &TCP_server->incomming_connection_queue[TCP_server->incomming_connection_queue_index % MAX_INCOMMING_CONNECTIONS]; diff --git a/toxcore/TCP_server.h b/toxcore/TCP_server.h index 57313038..498b1147 100644 --- a/toxcore/TCP_server.h +++ b/toxcore/TCP_server.h @@ -26,7 +26,7 @@ #include "net_crypto.h" #include "onion.h" -#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) +#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__MACH__) #define MSG_NOSIGNAL 0 #endif diff --git a/toxcore/network.c b/toxcore/network.c index 47afab8e..7813ab03 100644 --- a/toxcore/network.c +++ b/toxcore/network.c @@ -150,6 +150,21 @@ int set_socket_nonblock(sock_t sock) #endif } +/* Set socket to not emit SIGPIPE + * + * return 1 on success + * return 0 on failure + */ +int set_socket_nosigpipe(sock_t sock) +{ +#if defined(__MACH__) + int set = 1; + return (setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int)) == 0); +#else + return 1; +#endif +} + /* Set socket to dual (IPv4 + IPv6 socket) * * return 1 on success diff --git a/toxcore/network.h b/toxcore/network.h index 42ade800..ef040bf3 100644 --- a/toxcore/network.h +++ b/toxcore/network.h @@ -332,6 +332,13 @@ void kill_sock(sock_t sock); */ int set_socket_nonblock(sock_t sock); +/* Set socket to not emit SIGPIPE + * + * return 1 on success + * return 0 on failure + */ +int set_socket_nosigpipe(sock_t sock); + /* Set socket to dual (IPv4 + IPv6 socket) * * return 1 on success From b16af69d9252faf730d12d3a452bcd76b2cc686f Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sun, 13 Apr 2014 20:40:48 -0400 Subject: [PATCH 004/117] TCP_client pretty much done? Now next step is integrating it in tox. Added TCP server functionality to bootstrap server (define TCP_RELAY_ENABLED to enable it.) --- other/DHT_bootstrap.c | 19 +++++++++++ toxcore/TCP_client.c | 79 +++++++++++++++++++++++++++++++++++++++++-- toxcore/TCP_client.h | 17 ++++++++++ 3 files changed, 112 insertions(+), 3 deletions(-) diff --git a/other/DHT_bootstrap.c b/other/DHT_bootstrap.c index 291d6589..50d473a9 100644 --- a/other/DHT_bootstrap.c +++ b/other/DHT_bootstrap.c @@ -31,6 +31,10 @@ #include "../toxcore/friend_requests.h" #include "../toxcore/util.h" +#ifdef TCP_RELAY_ENABLED +#include "../toxcore/TCP_server.h" +#endif + #include "../testing/misc_tools.c" #ifdef DHT_NODE_EXTRA_PACKETS @@ -129,6 +133,18 @@ int main(int argc, char *argv[]) printf("Public key: "); uint32_t i; +#ifdef TCP_RELAY_ENABLED +#define NUM_PORTS 3 + uint16_t ports[NUM_PORTS] = {443, 3389, PORT}; + TCP_Server *tcp_s = new_TCP_server(ipv6enabled, NUM_PORTS, ports, dht->self_public_key, dht->self_secret_key, onion); + + if (tcp_s == NULL) { + printf("TCP server failed to initialize.\n"); + exit(1); + } + +#endif + FILE *file; file = fopen("PUBLIC_ID.txt", "w"); @@ -177,6 +193,9 @@ int main(int argc, char *argv[]) last_LANdiscovery = unix_time(); } +#ifdef TCP_RELAY_ENABLED + do_TCP_server(tcp_s); +#endif networking_poll(dht->c->lossless_udp->net); c_sleep(1); diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c index 18f63c5f..b8877018 100644 --- a/toxcore/TCP_client.c +++ b/toxcore/TCP_client.c @@ -171,7 +171,7 @@ static int write_packet_TCP_secure_connection(TCP_Client_Connection *con, uint8_ * return 0 if could not send packet. * return -1 on failure (connection must be killed). */ -static int send_routing_request(TCP_Client_Connection *con, uint8_t *public_key) +int send_routing_request(TCP_Client_Connection *con, uint8_t *public_key) { uint8_t packet[1 + crypto_box_PUBLICKEYBYTES]; packet[0] = TCP_PACKET_ROUTING_REQUEST; @@ -179,6 +179,28 @@ static int send_routing_request(TCP_Client_Connection *con, uint8_t *public_key) return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); } +void routing_response_handler(TCP_Client_Connection *con, int (*response_callback)(void *object, uint8_t connection_id, + uint8_t *public_key), void *object) +{ + con->response_callback = response_callback; + con->response_callback_object = object; +} + +void routing_status_handler(TCP_Client_Connection *con, int (*status_callback)(void *object, uint8_t connection_id, + uint8_t status), void *object) +{ + con->status_callback = status_callback; + con->status_callback_object = object; +} + +void routing_data_handler(TCP_Client_Connection *con, int (*data_callback)(void *object, uint8_t connection_id, + uint8_t *data, uint16_t length), void *object) +{ + con->data_callback = data_callback; + con->data_callback_object = object; +} + + /* return 1 on success. * return 0 if could not send packet. * return -1 on failure (connection must be killed). @@ -290,19 +312,68 @@ TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, uint8_t *public_key, */ static int handle_TCP_packet(TCP_Client_Connection *conn, uint8_t *data, uint16_t length) { - if (length == 0) + if (length <= 1) return -1; switch (data[0]) { case TCP_PACKET_ROUTING_RESPONSE: { + if (length != 1 + 1 + crypto_box_PUBLICKEYBYTES) + return -1; + + if (data[1] < NUM_RESERVED_PORTS) + return 0; + + uint8_t con_id = data[1] - NUM_RESERVED_PORTS; + + if (conn->connections[con_id].status != 0) + return -1; + + conn->connections[con_id].status = 1; + memcpy(conn->connections[con_id].public_key, data + 2, crypto_box_PUBLICKEYBYTES); + + if (conn->response_callback) + conn->response_callback(conn->response_callback_object, con_id, conn->connections[con_id].public_key); + return 0; } case TCP_PACKET_CONNECTION_NOTIFICATION: { + if (length != 1 + 1) + return -1; + + if (data[1] < NUM_RESERVED_PORTS) + return -1; + + uint8_t con_id = data[1] - NUM_RESERVED_PORTS; + + if (conn->connections[con_id].status != 1) + return -1; + + conn->connections[con_id].status = 2; + + if (conn->status_callback) + conn->status_callback(conn->status_callback_object, con_id, conn->connections[con_id].status); + return 0; } case TCP_PACKET_DISCONNECT_NOTIFICATION: { + if (length != 1 + 1) + return -1; + + if (data[1] < NUM_RESERVED_PORTS) + return -1; + + uint8_t con_id = data[1] - NUM_RESERVED_PORTS; + + if (conn->connections[con_id].status != 2) + return -1; + + conn->connections[con_id].status = 1; + + if (conn->status_callback) + conn->status_callback(conn->status_callback_object, con_id, conn->connections[con_id].status); + return 0; } @@ -344,7 +415,9 @@ static int handle_TCP_packet(TCP_Client_Connection *conn, uint8_t *data, uint16_ return -1; uint8_t con_id = data[0] - NUM_RESERVED_PORTS; - //TODO + + if (conn->data_callback) + conn->data_callback(conn->data_callback_object, con_id, data + 1, length - 1); } } diff --git a/toxcore/TCP_client.h b/toxcore/TCP_client.h index e096ae62..66084a64 100644 --- a/toxcore/TCP_client.h +++ b/toxcore/TCP_client.h @@ -60,6 +60,12 @@ typedef struct { uint8_t status; /* 0 if not used, 1 if other is offline, 2 if other is online. */ uint8_t public_key[crypto_box_PUBLICKEYBYTES]; } connections[NUM_CLIENT_CONNECTIONS]; + int (*response_callback)(void *object, uint8_t connection_id, uint8_t *public_key); + void *response_callback_object; + int (*status_callback)(void *object, uint8_t connection_id, uint8_t status); + void *status_callback_object; + int (*data_callback)(void *object, uint8_t connection_id, uint8_t *data, uint16_t length); + void *data_callback_object; int (*onion_callback)(void *object, uint8_t *data, uint16_t length); void *onion_callback_object; @@ -86,5 +92,16 @@ int send_onion_request(TCP_Client_Connection *con, uint8_t *data, uint16_t lengt void onion_response_handler(TCP_Client_Connection *con, int (*onion_callback)(void *object, uint8_t *data, uint16_t length), void *object); +/* return 1 on success. + * return 0 if could not send packet. + * return -1 on failure (connection must be killed). + */ +int send_routing_request(TCP_Client_Connection *con, uint8_t *public_key); +void routing_response_handler(TCP_Client_Connection *con, int (*response_callback)(void *object, uint8_t connection_id, + uint8_t *public_key), void *object); +void routing_status_handler(TCP_Client_Connection *con, int (*status_callback)(void *object, uint8_t connection_id, + uint8_t status), void *object); +void routing_data_handler(TCP_Client_Connection *con, int (*data_callback)(void *object, uint8_t connection_id, + uint8_t *data, uint16_t length), void *object); #endif From 1808c88c79f7f19bd3cce1bebd9832bb8e0aac28 Mon Sep 17 00:00:00 2001 From: Steven Noonan Date: Sun, 13 Apr 2014 04:26:54 -0700 Subject: [PATCH 005/117] toxav/Makefile.inc: add LIBSODIUM_* variables to flags These are needed if libsodium paths are discovered by 'configure'. Most systems don't need this just because libsodium is already on the header/library search paths, but on e.g. Mac OS X this is required. Signed-off-by: Steven Noonan --- toxav/Makefile.inc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/toxav/Makefile.inc b/toxav/Makefile.inc index 0cad1840..ab9352d2 100644 --- a/toxav/Makefile.inc +++ b/toxav/Makefile.inc @@ -18,15 +18,18 @@ libtoxav_la_SOURCES = ../toxav/event.h \ libtoxav_la_CFLAGS = -I../toxcore \ -I../toxav \ + $(LIBSODIUM_CFLAGS) \ $(NACL_CFLAGS) \ $(AV_CFLAGS) \ $(PTHREAD_CFLAGS) libtoxav_la_LDFLAGS = $(TOXAV_LT_LDFLAGS) \ + $(LIBSODIUM_LDFLAGS) \ $(NACL_LDFLAGS) \ $(EXTRA_LT_LDFLAGS) libtoxav_la_LIBADD = libtoxcore.la \ + $(LIBSODIUM_LIBS) \ $(NACL_LIBS) \ $(PTHREAD_LIBS) \ $(AV_LIBS) From 20336c007690d92740e48f3c4fcad562fbaaa6e9 Mon Sep 17 00:00:00 2001 From: Steven Noonan Date: Sun, 13 Apr 2014 04:27:53 -0700 Subject: [PATCH 006/117] media.h: include 'opus.h' instead of 'opus/opus.h' The current 'opus/opus.h' works if your opus.h is in /usr/include/opus, as /usr/include is already in the header search path. If your opus header search path is found via pkg-config, however, you will get something like this: $ pkg-config --cflags opus -I/usr/local/Cellar/opus/1.1/include/opus Since this is pointing directly to include/opus, the 'opus/' prefix on the header include directive will break. Since 'opus.h' should work in both cases (as in both cases it will be discovered via pkg-config), just use the simpler 'opus.h'. Signed-off-by: Steven Noonan --- toxav/media.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toxav/media.h b/toxav/media.h index f5c5fbe4..57817516 100644 --- a/toxav/media.h +++ b/toxav/media.h @@ -36,7 +36,7 @@ #define VIDEO_CODEC_ENCODER_INTERFACE (vpx_codec_vp8_cx()) /* Audio encoding/decoding */ -#include +#include typedef enum _Capabilities { From 229b2b2dcdcab20f35063da9e69b6ef0ded70231 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Mon, 14 Apr 2014 16:59:48 -0400 Subject: [PATCH 007/117] Added function to TCP client and some tests. --- auto_tests/TCP_test.c | 81 +++++++++++++++++++++++++++++++++++++++++++ toxcore/TCP_client.c | 18 ++++++++++ toxcore/TCP_client.h | 7 ++++ 3 files changed, 106 insertions(+) diff --git a/auto_tests/TCP_test.c b/auto_tests/TCP_test.c index 2ae1dc78..ff30e8f6 100644 --- a/auto_tests/TCP_test.c +++ b/auto_tests/TCP_test.c @@ -291,6 +291,47 @@ START_TEST(test_some) } END_TEST +static int response_callback_good; +static uint8_t response_callback_connection_id; +static uint8_t response_callback_public_key[crypto_box_PUBLICKEYBYTES]; +static int response_callback(void *object, uint8_t connection_id, uint8_t *public_key) +{ + if (object != (void *)1) + return 1; + + response_callback_connection_id = connection_id; + memcpy(response_callback_public_key, public_key, crypto_box_PUBLICKEYBYTES); + response_callback_good++; +} +static int status_callback_good; +static uint8_t status_callback_connection_id; +static uint8_t status_callback_status; +static int status_callback(void *object, uint8_t connection_id, uint8_t status) +{ + if (object != (void *)2) + return 1; + + status_callback_connection_id = connection_id; + status_callback_status = status; + status_callback_good++; +} +static int data_callback_good; +static int data_callback(void *object, uint8_t connection_id, uint8_t *data, uint16_t length) +{ + if (object != (void *)3) + return 1; + + if (length != 5) + return 1; + + if (data[0] == 1 && data[1] == 2 && data[2] == 3 && data[3] == 4 && data[4] == 5) { + data_callback_good++; + return 0; + } + + return 1; +} + START_TEST(test_client) { unix_time_update(); @@ -332,6 +373,46 @@ START_TEST(test_client) c_sleep(50); ck_assert_msg(conn->status == TCP_CLIENT_CONFIRMED, "Wrong status. Expected: %u, is: %u", TCP_CLIENT_CONFIRMED, conn->status); + + uint8_t f2_public_key[crypto_box_PUBLICKEYBYTES]; + uint8_t f2_secret_key[crypto_box_SECRETKEYBYTES]; + crypto_box_keypair(f2_public_key, f2_secret_key); + TCP_Client_Connection *conn2 = new_TCP_connection(ip_port_tcp_s, self_public_key, f2_public_key, f2_secret_key); + routing_response_handler(conn, response_callback, (void *)1); + routing_status_handler(conn, status_callback, (void *)2); + routing_data_handler(conn, data_callback, (void *)3); + response_callback_good = status_callback_good = data_callback_good = 0; + c_sleep(50); + do_TCP_connection(conn); + do_TCP_connection(conn2); + c_sleep(50); + do_TCP_server(tcp_s); + c_sleep(50); + do_TCP_connection(conn); + do_TCP_connection(conn2); + c_sleep(50); + send_routing_request(conn, f2_public_key); + send_routing_request(conn2, f_public_key); + c_sleep(50); + do_TCP_server(tcp_s); + c_sleep(50); + do_TCP_connection(conn); + do_TCP_connection(conn2); + ck_assert_msg(response_callback_good == 1, "response callback not called"); + ck_assert_msg(memcmp(response_callback_public_key, f2_public_key, crypto_box_PUBLICKEYBYTES) == 0, "wrong public key"); + ck_assert_msg(status_callback_good == 1, "status callback not called"); + ck_assert_msg(status_callback_status == 2, "wrong status"); + ck_assert_msg(status_callback_connection_id == response_callback_connection_id, "connection ids not equal"); + c_sleep(50); + do_TCP_server(tcp_s); + uint8_t data[5] = {1, 2, 3, 4, 5}; + ck_assert_msg(send_data(conn2, 0, data, 5) == 1, "send data failed"); + c_sleep(50); + do_TCP_server(tcp_s); + c_sleep(50); + do_TCP_connection(conn); + do_TCP_connection(conn2); + ck_assert_msg(data_callback_good == 1, "data callback not called"); } END_TEST diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c index b8877018..b69b422e 100644 --- a/toxcore/TCP_client.c +++ b/toxcore/TCP_client.c @@ -193,6 +193,24 @@ void routing_status_handler(TCP_Client_Connection *con, int (*status_callback)(v con->status_callback_object = object; } +/* return 1 on success. + * return 0 if could not send packet. + * return -1 on failure. + */ +int send_data(TCP_Client_Connection *con, uint8_t con_id, uint8_t *data, uint16_t length) +{ + if (con_id >= NUM_CLIENT_CONNECTIONS) + return -1; + + if (con->connections[con_id].status != 2) + return -1; + + uint8_t packet[1 + length]; + packet[0] = con_id + NUM_RESERVED_PORTS; + memcpy(packet + 1, data, length); + return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); +} + void routing_data_handler(TCP_Client_Connection *con, int (*data_callback)(void *object, uint8_t connection_id, uint8_t *data, uint16_t length), void *object) { diff --git a/toxcore/TCP_client.h b/toxcore/TCP_client.h index 66084a64..7e8be22d 100644 --- a/toxcore/TCP_client.h +++ b/toxcore/TCP_client.h @@ -101,6 +101,13 @@ void routing_response_handler(TCP_Client_Connection *con, int (*response_callbac uint8_t *public_key), void *object); void routing_status_handler(TCP_Client_Connection *con, int (*status_callback)(void *object, uint8_t connection_id, uint8_t status), void *object); + + +/* return 1 on success. + * return 0 if could not send packet. + * return -1 on failure. + */ +int send_data(TCP_Client_Connection *con, uint8_t con_id, uint8_t *data, uint16_t length); void routing_data_handler(TCP_Client_Connection *con, int (*data_callback)(void *object, uint8_t connection_id, uint8_t *data, uint16_t length), void *object); From f9bf7b074acd29b0448d36a66db4339c6ae659c4 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 15 Apr 2014 18:09:07 -0400 Subject: [PATCH 008/117] Major protocol changes, this commit breaks all network compatibility. Removed a bunch of useless space from various structs. pack_nodes() and unpack_nodes() are now used to transmit lists of nodes for the DHT and onion parts. They provide a way to transmit both ipv6 and ipv4 nodes in the same packet in a portable way that takes as little space as possible without compression. Using pack_nodes, merged the send nodes and send nodes ipv6 packets into one packet greatly reducing the risk of amplification attacks. --- auto_tests/network_test.c | 5 +- docs/updates/DHT.md | 16 +- toxcore/DHT.c | 373 ++++++++++++++++---------------------- toxcore/DHT.h | 31 +++- toxcore/network.h | 18 -- toxcore/onion_announce.c | 19 +- toxcore/onion_client.c | 58 +++--- 7 files changed, 220 insertions(+), 300 deletions(-) diff --git a/auto_tests/network_test.c b/auto_tests/network_test.c index 3b4b50cd..afd90e7a 100644 --- a/auto_tests/network_test.c +++ b/auto_tests/network_test.c @@ -136,9 +136,8 @@ START_TEST(test_struct_sizes) { ck_assert_msg(sizeof(IP4) == 4, "sizeof(IP4): expected result 4, got %u.", sizeof(IP4)); ck_assert_msg(sizeof(IP6) == 16, "sizeof(IP6): expected result 16, got %u.", sizeof(IP6)); - ck_assert_msg(sizeof(IP) == 20, "sizeof(IP): expected result 20, got %u.", sizeof(IP)); - ck_assert_msg(sizeof(IP_Port) == 24, "sizeof(IP_Port): expected result 24, got %u.", sizeof(IP_Port)); - ck_assert_msg(sizeof(IP4_Port) == 8, "sizeof(IP4_Port): expected result 8, got %u.", sizeof(IP4_Port)); + ck_assert_msg(sizeof(IP) == 17, "sizeof(IP): expected result 17, got %u.", sizeof(IP)); + ck_assert_msg(sizeof(IP_Port) == 19, "sizeof(IP_Port): expected result 19, got %u.", sizeof(IP_Port)); } END_TEST diff --git a/docs/updates/DHT.md b/docs/updates/DHT.md index db825a3c..9e94ab11 100644 --- a/docs/updates/DHT.md +++ b/docs/updates/DHT.md @@ -79,12 +79,9 @@ Protocol Node format: ``` -[char array (node_id), length=32 bytes][ip (in network byte order), length=4 bytes][port (in network byte order), length=2 bytes][Padding , length=2 bytes] +[uint8_t family (2 == IPv4, 10 == IPv6, 130 == TCP IPv4, 138 == TCP IPv6)][ip (in network byte order), length=4 bytes if ipv4, 16 bytes if ipv6][port (in network byte order), length=2 bytes][char array (node_id), length=32 bytes] ``` -see also: DHT.h (Node4_format struct) - -IPv6 Node format: -see: DHT.h (Node_format struct) +see also: DHT.h (pack_nodes() and unpack_nodes()) Valid queries and Responses: @@ -102,12 +99,7 @@ Packet contents: ``` Valid replies: a send_nodes packet -Send_nodes (response (for ipv4 addresses)): +Send_nodes (response (for all addresses)): ``` -[byte with value: 03][char array (client node_id), length=32 bytes][random 24 byte nonce][Encrypted with the nonce and private key of the sender:[Nodes in node format, length=40 * (number of nodes (maximum of 8 nodes)) bytes][Encrypted data, length=NODES_ENCRYPTED_MESSAGE_LENGTH bytes]] -``` - -Send_nodes_IPv6 (response (for ipv6 addresses)): -``` -[byte with value: 04][char array (client node_id), length=32 bytes][random 24 byte nonce][Encrypted with the nonce and private key of the sender:[Nodes in ipv6_node format, length=56 * (number of nodes (maximum of 8 nodes)) bytes][Encrypted data, length=NODES_ENCRYPTED_MESSAGE_LENGTH bytes]] +[byte with value: 04][char array (client node_id), length=32 bytes][random 24 byte nonce][Encrypted with the nonce and private key of the sender:[Nodes in node format, length=?? * (number of nodes (maximum of 8 nodes)) bytes][Encrypted data, length=NODES_ENCRYPTED_MESSAGE_LENGTH bytes]] ``` diff --git a/toxcore/DHT.c b/toxcore/DHT.c index 1089e2ff..98b488a2 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c @@ -179,6 +179,105 @@ void DHT_get_shared_key_sent(DHT *dht, uint8_t *shared_key, uint8_t *client_id) return get_shared_key(&dht->shared_keys_sent, shared_key, dht->self_secret_key, client_id); } +void to_net_family(IP *ip) +{ + if (ip->family == AF_INET) + ip->family = TOX_AF_INET; + else if (ip->family == AF_INET6) + ip->family = TOX_AF_INET6; +} + +void to_host_family(IP *ip) +{ + if (ip->family == TOX_AF_INET) + ip->family = AF_INET; + else if (ip->family == TOX_AF_INET6) + ip->family = AF_INET6; +} + +/* Pack number of nodes into data of maxlength length. + * + * return length of packed nodes on success. + * return -1 on failure. + */ +int pack_nodes(uint8_t *data, uint16_t length, Node_format *nodes, uint16_t number) +{ + uint32_t i, packed_length = 0; + + for (i = 0; i < number; ++i) { + if (nodes[i].ip_port.ip.family == AF_INET) { + uint32_t size = 1 + sizeof(IP4) + sizeof(uint16_t) + CLIENT_ID_SIZE; + + if (packed_length + size > length) + return -1; + + data[packed_length] = TOX_AF_INET; + memcpy(data + packed_length + 1, &nodes[i].ip_port.ip.ip4, sizeof(IP4)); + memcpy(data + packed_length + 1 + sizeof(IP4), &nodes[i].ip_port.port, sizeof(uint16_t)); + memcpy(data + packed_length + 1 + sizeof(IP4) + sizeof(uint16_t), nodes[i].client_id, CLIENT_ID_SIZE); + packed_length += size; + } else if (nodes[i].ip_port.ip.family == AF_INET6) { + uint32_t size = 1 + sizeof(IP6) + sizeof(uint16_t) + CLIENT_ID_SIZE; + + if (packed_length + size > length) + return -1; + + data[packed_length] = TOX_AF_INET6; + memcpy(data + packed_length + 1, &nodes[i].ip_port.ip.ip6, sizeof(IP6)); + memcpy(data + packed_length + 1 + sizeof(IP6), &nodes[i].ip_port.port, sizeof(uint16_t)); + memcpy(data + packed_length + 1 + sizeof(IP6) + sizeof(uint16_t), nodes[i].client_id, CLIENT_ID_SIZE); + packed_length += size; + } else { + return -1; + } + } + + return packed_length; +} + +/* Unpack data of length into nodes of size (in number of nodes). + * + * return number of unpacked nodes on success. + * return -1 on failure. + */ +int unpack_nodes(Node_format *nodes, uint16_t size, uint8_t *data, uint16_t length) +{ + uint32_t num = 0, len_processed = 0; + + while (num < size && len_processed < length) { + if (data[len_processed] == TOX_AF_INET) { + uint32_t size = 1 + sizeof(IP4) + sizeof(uint16_t) + CLIENT_ID_SIZE; + + if (len_processed + size > length) + return -1; + + nodes[num].ip_port.ip.family = AF_INET; + memcpy(&nodes[num].ip_port.ip.ip4, data + len_processed + 1, sizeof(IP4)); + memcpy(&nodes[num].ip_port.port, data + len_processed + 1 + sizeof(IP4), sizeof(uint16_t)); + memcpy(nodes[num].client_id, data + len_processed + 1 + sizeof(IP4) + sizeof(uint16_t), CLIENT_ID_SIZE); + len_processed += size; + ++num; + } else if (data[len_processed] == TOX_AF_INET6) { + uint32_t size = 1 + sizeof(IP6) + sizeof(uint16_t) + CLIENT_ID_SIZE; + + if (len_processed + size > length) + return -1; + + nodes[num].ip_port.ip.family = AF_INET6; + memcpy(&nodes[num].ip_port.ip.ip6, data + len_processed + 1, sizeof(IP6)); + memcpy(&nodes[num].ip_port.port, data + len_processed + 1 + sizeof(IP6), sizeof(uint16_t)); + memcpy(nodes[num].client_id, data + len_processed + 1 + sizeof(IP6) + sizeof(uint16_t), CLIENT_ID_SIZE); + len_processed += size; + ++num; + } else { + return -1; + } + } + + return num; +} + + /* Check if client with client_id is already in list of length length. * If it is then set its corresponding timestamp to current time. @@ -322,15 +421,15 @@ static uint8_t hardening_correct(Hardening *h) /* * helper for get_close_nodes(). argument list is a monster :D */ -static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nodes_list, +static void get_close_nodes_inner(uint8_t *client_id, Node_format *nodes_list, sa_family_t sa_family, Client_data *client_list, uint32_t client_list_length, uint32_t *num_nodes_ptr, uint8_t is_LAN, uint8_t want_good) { - if ((sa_family != AF_INET) && (sa_family != AF_INET6)) + if ((sa_family != AF_INET) && (sa_family != AF_INET6) && (sa_family != 0)) return; uint32_t num_nodes = *num_nodes_ptr; - int ipv46x, j, closest; + int j, closest; uint32_t i; for (i = 0; i < client_list_length; i++) { @@ -342,39 +441,22 @@ static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nod IPPTsPng *ipptp = NULL; - if (sa_family == AF_INET) + if (sa_family == AF_INET) { ipptp = &client->assoc4; - else + } else if (sa_family == AF_INET6) { ipptp = &client->assoc6; + } else { + if (client->assoc4.timestamp >= client->assoc6.timestamp) { + ipptp = &client->assoc4; + } else { + ipptp = &client->assoc6; + } + } /* node not in a good condition? */ if (is_timeout(ipptp->timestamp, BAD_NODE_TIMEOUT)) continue; - IP *client_ip = &ipptp->ip_port.ip; - - /* - * Careful: AF_INET isn't seen as AF_INET on dual-stack sockets for - * our connections, instead we have to look if it is an embedded - * IPv4-in-IPv6 here and convert it down in sendnodes(). - */ - sa_family_t ip_treat_as_family = client_ip->family; - - 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, - * all storing functions should already convert down to IPv4) */ - if (IN6_IS_ADDR_V4MAPPED(&client_ip->ip6.in6_addr)) - ip_treat_as_family = AF_INET; - } - - ipv46x = !(sa_family == ip_treat_as_family); - - /* node address of the wrong family? */ - if (ipv46x) - continue; - /* don't send LAN ips to non LAN peers */ if (LAN_ip(ipptp->ip_port.ip) == 0 && !is_LAN) continue; @@ -428,7 +510,7 @@ static int get_somewhat_close_nodes(DHT *dht, uint8_t *client_id, Node_format *n uint8_t is_LAN, uint8_t want_good) { uint32_t num_nodes = 0, i; - get_close_nodes_inner(dht, client_id, nodes_list, sa_family, + get_close_nodes_inner(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 @@ -438,7 +520,7 @@ static int get_somewhat_close_nodes(DHT *dht, uint8_t *client_id, Node_format *n &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, + get_close_nodes_inner(client_id, nodes_list, sa_family, dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, &num_nodes, is_LAN, 0); @@ -456,6 +538,7 @@ int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_fa return get_somewhat_close_nodes(dht, client_id, nodes_list, sa_family, is_LAN, want_good); #ifdef ENABLE_ASSOC_DHT + //TODO: assoc, sa_family 0 (don't care if ipv4 or ipv6) support. Client_data *result[MAX_SENT_NODES]; Assoc_close_entries request; @@ -907,95 +990,6 @@ static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cli return sendpacket(dht->net, ip_port, data, sizeof(data)); } -/* Send a send nodes response. */ -/* because of BINARY compatibility, the Node_format MUST BE Node4_format, - * IPv6 nodes are sent in a different message - * encrypted_data must be of size NODES_ENCRYPTED_MESSAGE_LENGTH */ -static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint8_t *encrypted_data, - uint8_t *shared_encryption_key) -{ - /* Check if packet is going to be sent to ourself. */ - if (id_equal(public_key, dht->self_public_key)) - return -1; - - size_t Node4_format_size = sizeof(Node4_format); - uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES - + Node4_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES]; - - Node_format nodes_list[MAX_SENT_NODES]; - uint32_t num_nodes = get_close_nodes(dht, client_id, nodes_list, AF_INET, LAN_ip(ip_port.ip) == 0, 1); - - if (num_nodes == 0) - return 0; - - uint8_t plain[Node4_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH]; - uint8_t encrypt[Node4_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES]; - uint8_t nonce[crypto_box_NONCEBYTES]; - new_nonce(nonce); - - Node4_format *nodes4_list = (Node4_format *)(plain); - uint32_t i, num_nodes_ok = 0; - - for (i = 0; i < num_nodes; i++) { - memcpy(nodes4_list[num_nodes_ok].client_id, nodes_list[i].client_id, CLIENT_ID_SIZE); - nodes4_list[num_nodes_ok].ip_port.port = nodes_list[i].ip_port.port; - - IP *node_ip = &nodes_list[i].ip_port.ip; - - if ((node_ip->family == AF_INET6) && IN6_IS_ADDR_V4MAPPED(&node_ip->ip6.in6_addr)) - /* embedded IPv4-in-IPv6 address: return it in regular sendnodes packet */ - nodes4_list[num_nodes_ok].ip_port.ip.uint32 = node_ip->ip6.uint32[3]; - else if (node_ip->family == AF_INET) - nodes4_list[num_nodes_ok].ip_port.ip.uint32 = node_ip->ip4.uint32; - else /* shouldn't happen */ - continue; - - num_nodes_ok++; - } - - if (num_nodes_ok < num_nodes) { - /* shouldn't happen */ - num_nodes = num_nodes_ok; - } - - memcpy(plain + num_nodes * Node4_format_size, encrypted_data, NODES_ENCRYPTED_MESSAGE_LENGTH); - int len = encrypt_data_fast( shared_encryption_key, - nonce, - plain, - num_nodes * Node4_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH, - encrypt ); - - if ((unsigned int)len != num_nodes * Node4_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH + - crypto_box_MACBYTES) - return -1; - - data[0] = NET_PACKET_SEND_NODES; - 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->net, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len); -} - -void to_net_family(IP *ip) -{ - ip->padding[0] = 0; - ip->padding[1] = 0; - ip->padding[2] = 0; - - if (ip->family == AF_INET) - ip->family = TOX_AF_INET; - else if (ip->family == AF_INET6) - ip->family = TOX_AF_INET6; -} - -void to_host_family(IP *ip) -{ - if (ip->family == TOX_AF_INET) - ip->family = AF_INET; - else if (ip->family == TOX_AF_INET6) - ip->family = AF_INET6; -} /* Send a send nodes response: message for IPv6 nodes */ static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint8_t *encrypted_data, uint8_t *shared_encryption_key) @@ -1009,7 +1003,7 @@ static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_ + Node_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES]; Node_format nodes_list[MAX_SENT_NODES]; - uint32_t num_nodes = get_close_nodes(dht, client_id, nodes_list, AF_INET6, LAN_ip(ip_port.ip) == 0, 1); + uint32_t num_nodes = get_close_nodes(dht, client_id, nodes_list, 0, LAN_ip(ip_port.ip) == 0, 1); if (num_nodes == 0) return 0; @@ -1019,20 +1013,19 @@ static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_ uint8_t nonce[crypto_box_NONCEBYTES]; new_nonce(nonce); - uint32_t i; + int nodes_length = pack_nodes(plain, Node_format_size * MAX_SENT_NODES, nodes_list, num_nodes); - for (i = 0; i < num_nodes; ++i) - to_net_family(&nodes_list[i].ip_port.ip); + if (nodes_length <= 0) + return -1; - memcpy(plain, nodes_list, num_nodes * Node_format_size); - memcpy(plain + num_nodes * Node_format_size, encrypted_data, NODES_ENCRYPTED_MESSAGE_LENGTH); + memcpy(plain + nodes_length, encrypted_data, NODES_ENCRYPTED_MESSAGE_LENGTH); int len = encrypt_data_fast( shared_encryption_key, nonce, plain, - num_nodes * Node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH, + nodes_length + NODES_ENCRYPTED_MESSAGE_LENGTH, encrypt ); - if ((unsigned int)len != num_nodes * Node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES) + if ((unsigned int)len != nodes_length + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES) return -1; data[0] = NET_PACKET_SEND_NODES_IPV6; @@ -1068,12 +1061,9 @@ static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32 if (len != CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH) return 1; - sendnodes(dht, source, packet + 1, plain, plain + CLIENT_ID_SIZE, shared_key); - sendnodes_ipv6(dht, source, packet + 1, plain, - plain + CLIENT_ID_SIZE, shared_key); /* TODO: prevent possible amplification attacks */ + sendnodes_ipv6(dht, source, packet + 1, plain, plain + CLIENT_ID_SIZE, shared_key); add_to_ping(dht->ping, packet + 1, source); - //send_ping_request(dht, source, packet + 1); /* TODO: make this smarter? */ return 0; } @@ -1108,15 +1098,12 @@ static uint8_t sent_getnode_to_node(DHT *dht, uint8_t *client_id, IP_Port node_i } /* Function is needed in following functions. */ -static int send_hardening_getnode_res(DHT *dht, Node_format *sendto, uint8_t *queried_client_id, Node_format *list, - uint16_t num_nodes); +static int send_hardening_getnode_res(DHT *dht, Node_format *sendto, uint8_t *queried_client_id, uint8_t *nodes_data, + uint16_t nodes_data_length); static int handle_sendnodes_core(void *object, IP_Port source, uint8_t *packet, uint32_t length, - size_t node_format_size, uint8_t *plain, uint16_t plain_length, uint32_t *num_nodes_out, Node_format *sendback_node) + Node_format *plain_nodes, uint16_t size_plain_nodes, uint32_t *num_nodes_out) { - if (plain_length != MAX_SENT_NODES * node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH) - return 1; - DHT *dht = object; uint32_t cid_size = 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES; @@ -1125,27 +1112,33 @@ static int handle_sendnodes_core(void *object, IP_Port source, uint8_t *packet, uint32_t data_size = length - cid_size; - if ((data_size % node_format_size) != 0) /* invalid length */ + if (data_size == 0) return 1; - uint32_t num_nodes = data_size / node_format_size; - - if (num_nodes > MAX_SENT_NODES) /* too long */ + if (data_size > sizeof(Node_format) * MAX_SENT_NODES) /* invalid length */ return 1; + uint8_t plain[data_size + NODES_ENCRYPTED_MESSAGE_LENGTH]; uint8_t shared_key[crypto_box_BEFORENMBYTES]; DHT_get_shared_key_sent(dht, shared_key, packet + 1); int len = decrypt_data_fast( shared_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, + data_size + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES, plain); - if ((unsigned int)len != num_nodes * node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH) + if ((unsigned int)len != sizeof(plain)) return 1; - if (!sent_getnode_to_node(dht, packet + 1, source, plain + num_nodes * node_format_size, sendback_node)) + Node_format sendback_node; + + if (!sent_getnode_to_node(dht, packet + 1, source, plain + data_size, &sendback_node)) + return 1; + + int num_nodes = unpack_nodes(plain_nodes, size_plain_nodes, plain, data_size); + + if (num_nodes <= 0) return 1; /* store the address the *request* was sent to */ @@ -1153,79 +1146,28 @@ static int handle_sendnodes_core(void *object, IP_Port source, uint8_t *packet, *num_nodes_out = num_nodes; - return 0; -} - -static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length) -{ - DHT *dht = object; - size_t node4_format_size = sizeof(Node4_format); - uint8_t plain[node4_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH]; - uint32_t num_nodes; - - Node_format sendback_node; - - if (handle_sendnodes_core(object, source, packet, length, node4_format_size, plain, sizeof(plain), &num_nodes, - &sendback_node)) - return 1; - - if (num_nodes == 0) - return 0; - - Node4_format *nodes4_list = (Node4_format *)(plain); - - uint64_t time_now = unix_time(); - IPPTs ippts; - ippts.ip_port.ip.family = AF_INET; - ippts.timestamp = time_now; - - uint32_t i; - - Node_format nodes_list[MAX_SENT_NODES]; - - for (i = 0; i < num_nodes; i++) - if ((nodes4_list[i].ip_port.ip.uint32 != 0) && (nodes4_list[i].ip_port.ip.uint32 != (uint32_t)~0)) { - ippts.ip_port.ip.ip4.uint32 = nodes4_list[i].ip_port.ip.uint32; - ippts.ip_port.port = nodes4_list[i].ip_port.port; - - send_ping_request(dht->ping, ippts.ip_port, nodes4_list[i].client_id); - returnedip_ports(dht, ippts.ip_port, nodes4_list[i].client_id, packet + 1); - - memcpy(nodes_list[i].client_id, nodes4_list[i].client_id, CLIENT_ID_SIZE); - ipport_copy(&nodes_list[i].ip_port, &ippts.ip_port); - - } - - send_hardening_getnode_res(dht, &sendback_node, packet + 1, nodes_list, num_nodes); + send_hardening_getnode_res(dht, &sendback_node, packet + 1, plain, data_size); return 0; } static int handle_sendnodes_ipv6(void *object, IP_Port source, uint8_t *packet, uint32_t length) { DHT *dht = object; - size_t node_format_size = sizeof(Node_format); - uint8_t plain[node_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH]; + Node_format plain_nodes[MAX_SENT_NODES]; uint32_t num_nodes; - Node_format sendback_node; - - if (handle_sendnodes_core(object, source, packet, length, node_format_size, plain, sizeof(plain), &num_nodes, - &sendback_node)) + if (handle_sendnodes_core(object, source, packet, length, plain_nodes, MAX_SENT_NODES, &num_nodes)) return 1; if (num_nodes == 0) return 0; - Node_format *nodes_list = (Node_format *)(plain); uint32_t i; - send_hardening_getnode_res(dht, &sendback_node, packet + 1, nodes_list, num_nodes); for (i = 0; i < num_nodes; i++) { - to_host_family(&nodes_list[i].ip_port.ip); - - if (ipport_isset(&nodes_list[i].ip_port)) { - send_ping_request(dht->ping, nodes_list[i].ip_port, nodes_list[i].client_id); - returnedip_ports(dht, nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1); + if (ipport_isset(&plain_nodes[i].ip_port)) { + send_ping_request(dht->ping, plain_nodes[i].ip_port, plain_nodes[i].client_id); + returnedip_ports(dht, plain_nodes[i].ip_port, plain_nodes[i].client_id, packet + 1); } } @@ -1977,17 +1919,17 @@ static int send_hardening_getnode_req(DHT *dht, Node_format *dest, Node_format * } /* Send a get node hardening response */ -static int send_hardening_getnode_res(DHT *dht, Node_format *sendto, uint8_t *queried_client_id, Node_format *list, - uint16_t num_nodes) +static int send_hardening_getnode_res(DHT *dht, Node_format *sendto, uint8_t *queried_client_id, uint8_t *nodes_data, + uint16_t nodes_data_length) { if (!ip_isset(&sendto->ip_port.ip)) return -1; uint8_t packet[MAX_DATA_SIZE]; - uint8_t data[1 + CLIENT_ID_SIZE + num_nodes * sizeof(Node_format)]; + uint8_t data[1 + CLIENT_ID_SIZE + nodes_data_length]; 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)); + memcpy(data + 1 + CLIENT_ID_SIZE, nodes_data, nodes_data_length); int len = create_request(dht->self_public_key, dht->self_secret_key, packet, sendto->client_id, data, sizeof(data), CRYPTO_PACKET_HARDENING); @@ -2075,28 +2017,22 @@ static int handle_hardening(void *object, IP_Port source, uint8_t *source_pubkey if (length <= CLIENT_ID_SIZE + 1) return 1; - if ((length - 1 - CLIENT_ID_SIZE) % sizeof(Node_format) != 0) + if (length > 1 + CLIENT_ID_SIZE + sizeof(Node_format) * MAX_SENT_NODES) return 1; - uint16_t num = (length - 1 - CLIENT_ID_SIZE) / sizeof(Node_format); + uint16_t length_nodes = length - 1 - CLIENT_ID_SIZE; + Node_format nodes[MAX_SENT_NODES]; + int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, packet + 1 + CLIENT_ID_SIZE, length_nodes); /* TODO: MAX_SENT_NODES nodes should be returned at all times (right now we have a small network size so it could cause problems for testing and etc..) */ - if (num > MAX_SENT_NODES || num == 0) + if (num_nodes <= 0) return 1; - Node_format nodes[num]; - memcpy(nodes, packet + 1 + CLIENT_ID_SIZE, sizeof(Node_format)*num); - uint32_t i; - - for (i = 0; i < num; ++i) - to_host_family(&nodes[i].ip_port.ip); - /* NOTE: This should work for now but should be changed to something better. */ - if (have_nodes_closelist(dht, nodes, num) < (uint32_t)((num + 2) / 2)) + if (have_nodes_closelist(dht, nodes, num_nodes) < (uint32_t)((num_nodes + 2) / 2)) return 1; - IPPTsPng *temp = get_closelist_IPPTsPng(dht, packet + 1, nodes[0].ip_port.ip.family); if (temp == NULL) @@ -2329,7 +2265,6 @@ DHT *new_DHT(Net_Crypto *c) } 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); diff --git a/toxcore/DHT.h b/toxcore/DHT.h index 3d2722f8..73c44e9b 100644 --- a/toxcore/DHT.h +++ b/toxcore/DHT.h @@ -52,6 +52,8 @@ /* Redefinitions of variables for safe transfer over wire. */ #define TOX_AF_INET 2 #define TOX_AF_INET6 10 +#define TOX_TCP_INET 130 +#define TOX_TCP_INET6 138 /* 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 @@ -128,16 +130,27 @@ typedef struct { NAT nat; } DHT_Friend; -/* this must be kept even if IP_Port is expanded: wire compatibility */ -typedef struct { - uint8_t client_id[CLIENT_ID_SIZE]; - IP4_Port ip_port; -} Node4_format; - -typedef struct { +typedef struct __attribute__ ((__packed__)) +{ uint8_t client_id[CLIENT_ID_SIZE]; IP_Port ip_port; -} Node_format; +} +Node_format; + +/* Pack number of nodes into data of maxlength length. + * + * return length of packed nodes on success. + * return -1 on failure. + */ +int pack_nodes(uint8_t *data, uint16_t length, Node_format *nodes, uint16_t number); + +/* Unpack data of length into nodes of size (in number of nodes). + * + * return number of unpacked nodes on success. + * return -1 on failure. + */ +int unpack_nodes(Node_format *nodes, uint16_t size, uint8_t *data, uint16_t length); + /*----------------------------------------------------------------------------------*/ /* struct to store some shared keys so we don't have to regenerate them for each request. */ @@ -251,7 +264,7 @@ int id_closest(uint8_t *id, uint8_t *id1, uint8_t *id2); /* Get the (maximum MAX_SENT_NODES) closest nodes to client_id we know * and put them in nodes_list (must be MAX_SENT_NODES big). * - * sa_family = family (IPv4 or IPv6)? + * sa_family = family (IPv4 or IPv6) (0 if we don't care)? * is_LAN = return some LAN ips (true or false) * want_good = do we want tested nodes or not? (TODO) * diff --git a/toxcore/network.h b/toxcore/network.h index ef040bf3..4fca795b 100644 --- a/toxcore/network.h +++ b/toxcore/network.h @@ -161,9 +161,6 @@ typedef int sock_t; #define TOX_PORTRANGE_TO 33545 #define TOX_PORT_DEFAULT TOX_PORTRANGE_FROM - -/* TODO: remove padding bytes next time we need to break compatibility with old versions of core. */ - typedef union __attribute__ ((__packed__)) { uint8_t uint8[4]; @@ -186,8 +183,6 @@ IP6; typedef struct __attribute__ ((__packed__)) { uint8_t family; - /* Not used for anything right now. */ - uint8_t padding[3]; union { IP4 ip4; IP6 ip6; @@ -195,22 +190,9 @@ typedef struct __attribute__ ((__packed__)) } IP; -typedef union __attribute__ ((__packed__)) -{ - struct { - IP4 ip; - uint16_t port; - /* Not used for anything right now. */ - uint16_t padding; - }; - uint8_t uint8[8]; -} -IP4_Port; - typedef struct __attribute__ ((__packed__)) IP_Port { IP ip; uint16_t port; - uint16_t padding; } IP_Port; #define TOX_ENABLE_IPV6_DEFAULT 1 diff --git a/toxcore/onion_announce.c b/toxcore/onion_announce.c index 331e54d8..a1e5495e 100644 --- a/toxcore/onion_announce.c +++ b/toxcore/onion_announce.c @@ -247,14 +247,8 @@ static int handle_announce_request(void *object, IP_Port source, uint8_t *packet /*Respond with a announce response packet*/ Node_format nodes_list[MAX_SENT_NODES]; - uint32_t num_nodes = get_close_nodes(onion_a->dht, plain + ONION_PING_ID_SIZE, nodes_list, source.ip.family, - LAN_ip(source.ip) == 0, 1); - - uint32_t i; - - for (i = 0; i < num_nodes; ++i) - to_net_family(&nodes_list[i].ip_port.ip); - + uint32_t num_nodes = get_close_nodes(onion_a->dht, plain + ONION_PING_ID_SIZE, nodes_list, 0, LAN_ip(source.ip) == 0, + 1); uint8_t nonce[crypto_box_NONCEBYTES]; random_nonce(nonce); @@ -274,13 +268,16 @@ static int handle_announce_request(void *object, IP_Port source, uint8_t *packet } } - memcpy(pl + 1 + ONION_PING_ID_SIZE, nodes_list, num_nodes * sizeof(Node_format)); + int nodes_length = pack_nodes(pl + 1 + ONION_PING_ID_SIZE, sizeof(nodes_list), nodes_list, num_nodes); + + if (nodes_length <= 0) + return 1; uint8_t data[ONION_ANNOUNCE_RESPONSE_MAX_SIZE]; - len = encrypt_data_fast(shared_key, nonce, pl, 1 + ONION_PING_ID_SIZE + num_nodes * sizeof(Node_format), + len = encrypt_data_fast(shared_key, nonce, pl, 1 + ONION_PING_ID_SIZE + nodes_length, data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES); - if ((uint32_t)len != 1 + ONION_PING_ID_SIZE + num_nodes * sizeof(Node_format) + crypto_box_MACBYTES) + if (len != 1 + ONION_PING_ID_SIZE + nodes_length + crypto_box_MACBYTES) return 1; data[0] = NET_PACKET_ANNOUNCE_RESPONSE; diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index 329b1d13..439a80c7 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c @@ -345,8 +345,6 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, Node_format *n if (*ping_nodes_sent_second > MAX_PING_NODES_SECOND_PEER) return 0; - to_host_family(&nodes[i].ip_port.ip); - if (!lan_ips_accepted) if (LAN_ip(nodes[i].ip_port.ip) == 0) continue; @@ -377,10 +375,7 @@ static int handle_announce_response(void *object, IP_Port source, uint8_t *packe if (length < ONION_ANNOUNCE_RESPONSE_MIN_SIZE || length > ONION_ANNOUNCE_RESPONSE_MAX_SIZE) return 1; - if ((length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE) % sizeof(Node_format) != 0) - return 1; - - uint16_t num_nodes = (length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE) / sizeof(Node_format); + uint16_t len_nodes = length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE; uint8_t public_key[crypto_box_PUBLICKEYBYTES]; IP_Port ip_port; @@ -389,7 +384,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[1 + ONION_PING_ID_SIZE + num_nodes * sizeof(Node_format)]; + uint8_t plain[1 + ONION_PING_ID_SIZE + len_nodes]; int len = -1; if (num == 0) { @@ -409,15 +404,19 @@ static int handle_announce_response(void *object, IP_Port source, uint8_t *packe if ((uint32_t)len != sizeof(plain)) return 1; - if (client_add_to_list(onion_c, num, public_key, ip_port, plain[0], plain + 1, source) == -1) return 1; - Node_format nodes[MAX_SENT_NODES]; - memcpy(nodes, plain + 1 + ONION_PING_ID_SIZE, num_nodes * sizeof(Node_format)); + if (len_nodes != 0) { + Node_format nodes[MAX_SENT_NODES]; + int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, plain + 1 + ONION_PING_ID_SIZE, len_nodes); - if (client_ping_nodes(onion_c, num, nodes, num_nodes, source) == -1) - return 1; + if (num_nodes <= 0) + return 1; + + if (client_ping_nodes(onion_c, num, nodes, num_nodes, source) == -1) + return 1; + } return 0; } @@ -469,9 +468,6 @@ static int handle_fakeid_announce(void *object, uint8_t *source_pubkey, uint8_t if (length > FAKEID_DATA_MAX_LENGTH) return 1; - if ((length - FAKEID_DATA_MIN_LENGTH) % sizeof(Node_format) != 0) - return 1; - int friend_num = onion_friend_num(onion_c, source_pubkey); if (friend_num == -1) @@ -500,14 +496,20 @@ static int handle_fakeid_announce(void *object, uint8_t *source_pubkey, uint8_t 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 + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES, sizeof(nodes)); - uint32_t i; + uint16_t len_nodes = length - FAKEID_DATA_MIN_LENGTH; - for (i = 0; i < num_nodes; ++i) { - to_host_family(&nodes[i].ip_port.ip); - DHT_getnodes(onion_c->dht, &nodes[i].ip_port, nodes[i].client_id, onion_c->friends_list[friend_num].fake_client_id); + if (len_nodes != 0) { + Node_format nodes[MAX_SENT_NODES]; + int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, data + 1 + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES, len_nodes); + + if (num_nodes <= 0) + return 1; + + int i; + + for (i = 0; i < num_nodes; ++i) { + DHT_getnodes(onion_c->dht, &nodes[i].ip_port, nodes[i].client_id, onion_c->friends_list[friend_num].fake_client_id); + } } return 0; @@ -658,19 +660,19 @@ static int send_fakeid_announce(Onion_Client *onion_c, uint16_t friend_num, uint 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); - uint32_t i; + int nodes_len = pack_nodes(data + FAKEID_DATA_MIN_LENGTH, FAKEID_DATA_MAX_LENGTH - FAKEID_DATA_MIN_LENGTH, nodes, + num_nodes); - for (i = 0; i < num_nodes; ++i) - to_net_family(&nodes[i].ip_port.ip); + if (nodes_len <= 0) + return -1; - memcpy(data + FAKEID_DATA_MIN_LENGTH, nodes, sizeof(Node_format) * num_nodes); 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); + num1 = send_onion_data(onion_c, friend_num, data, FAKEID_DATA_MIN_LENGTH + nodes_len); if (onion_dht_both != 0) - num2 = send_dht_fakeid(onion_c, friend_num, data, FAKEID_DATA_MIN_LENGTH + sizeof(Node_format) * num_nodes); + num2 = send_dht_fakeid(onion_c, friend_num, data, FAKEID_DATA_MIN_LENGTH + nodes_len); if (num1 == -1) return num2; From be413de39624c6137e577e3bff14928d2cb873d3 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 15 Apr 2014 19:16:35 -0400 Subject: [PATCH 009/117] Fixed regression, announce responses can contain 0 nodes. --- auto_tests/onion_test.c | 1 + toxcore/onion_announce.c | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/auto_tests/onion_test.c b/auto_tests/onion_test.c index 2f244693..cd060b1f 100644 --- a/auto_tests/onion_test.c +++ b/auto_tests/onion_test.c @@ -186,6 +186,7 @@ START_TEST(test_basic) while (handled_test_3 == 0) { do_onion(onion1); do_onion(onion2); + c_sleep(50); } randombytes(sb_data, sizeof(sb_data)); diff --git a/toxcore/onion_announce.c b/toxcore/onion_announce.c index a1e5495e..7a60a235 100644 --- a/toxcore/onion_announce.c +++ b/toxcore/onion_announce.c @@ -268,10 +268,14 @@ static int handle_announce_request(void *object, IP_Port source, uint8_t *packet } } - int nodes_length = pack_nodes(pl + 1 + ONION_PING_ID_SIZE, sizeof(nodes_list), nodes_list, num_nodes); + int nodes_length = 0; - if (nodes_length <= 0) - return 1; + if (num_nodes != 0) { + nodes_length = pack_nodes(pl + 1 + ONION_PING_ID_SIZE, sizeof(nodes_list), nodes_list, num_nodes); + + if (nodes_length <= 0) + return 1; + } uint8_t data[ONION_ANNOUNCE_RESPONSE_MAX_SIZE]; len = encrypt_data_fast(shared_key, nonce, pl, 1 + ONION_PING_ID_SIZE + nodes_length, From 6578d930f8b3d4961c33283d1ece981af5c41586 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Wed, 16 Apr 2014 07:19:40 -0400 Subject: [PATCH 010/117] DHT_bootstrap.c now has TCP server functionality enabled. Fixed a regression (same type as last commit). --- other/DHT_bootstrap.c | 2 ++ toxcore/onion_client.c | 11 ++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/other/DHT_bootstrap.c b/other/DHT_bootstrap.c index 50d473a9..738c2a0c 100644 --- a/other/DHT_bootstrap.c +++ b/other/DHT_bootstrap.c @@ -31,6 +31,8 @@ #include "../toxcore/friend_requests.h" #include "../toxcore/util.h" +#define TCP_RELAY_ENABLED + #ifdef TCP_RELAY_ENABLED #include "../toxcore/TCP_server.h" #endif diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index 439a80c7..ca3ec560 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c @@ -660,11 +660,16 @@ static int send_fakeid_announce(Onion_Client *onion_c, uint16_t friend_num, uint 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); - int nodes_len = pack_nodes(data + FAKEID_DATA_MIN_LENGTH, FAKEID_DATA_MAX_LENGTH - FAKEID_DATA_MIN_LENGTH, nodes, + + int nodes_len = 0; + + if (num_nodes != 0) { + nodes_len = pack_nodes(data + FAKEID_DATA_MIN_LENGTH, FAKEID_DATA_MAX_LENGTH - FAKEID_DATA_MIN_LENGTH, nodes, num_nodes); - if (nodes_len <= 0) - return -1; + if (nodes_len <= 0) + return -1; + } int num1 = -1, num2 = -1; From cf33c2f9ad98edc50d50e018e214bb0b6180d96d Mon Sep 17 00:00:00 2001 From: "Carlos E. Garcia" Date: Wed, 16 Apr 2014 12:08:44 -0400 Subject: [PATCH 011/117] multiple spelling fixes --- docs/Group-Chats.md | 8 ++++---- docs/Prevent_Tracking.txt | 5 +++-- docs/TCP_Network.txt | 4 ++-- docs/av_api.md | 2 +- docs/updates/Crypto.md | 2 +- m4/pkg.m4 | 2 +- other/DHTnodes | 2 +- other/fun/cracker.c | 2 +- toxav/msi.c | 24 ++++++++++++------------ toxav/msi.h | 6 +++--- toxav/phone.c | 4 ++-- toxcore/DHT.c | 18 +++++++++--------- toxcore/DHT.h | 2 +- toxcore/Lossless_UDP.c | 2 +- toxcore/Lossless_UDP.h | 2 +- toxcore/Messenger.c | 2 +- toxcore/Messenger.h | 4 ++-- toxcore/TCP_server.c | 2 +- toxcore/TCP_server.h | 2 +- toxcore/assoc.c | 2 +- toxcore/net_crypto.c | 2 +- toxcore/net_crypto.h | 2 +- toxcore/onion_client.c | 6 +++--- toxcore/onion_client.h | 4 ++-- toxcore/tox.c | 2 +- toxcore/tox.h | 10 +++++----- 26 files changed, 62 insertions(+), 61 deletions(-) diff --git a/docs/Group-Chats.md b/docs/Group-Chats.md index e318613d..5e00b550 100644 --- a/docs/Group-Chats.md +++ b/docs/Group-Chats.md @@ -21,18 +21,18 @@ See DHT, currently uses the IPv6 Node_format. Get nodes (Request): Packet contents: ``` -[char with a value of 48][Bob's (The reciever's) Public key (client_id) (32 bytes))][Alice's (The sender's) Public key (client_id) (32 bytes)][Random nonce (24 bytes)][Encrypted with the nonce, private key of the sender and public key of the reciever:[char with a value of 48][random 8 byte (ping_id)] +[char with a value of 48][Bob's (The receiver's) Public key (client_id) (32 bytes))][Alice's (The sender's) Public key (client_id) (32 bytes)][Random nonce (24 bytes)][Encrypted with the nonce, private key of the sender and public key of the receiver:[char with a value of 48][random 8 byte (ping_id)] ``` Valid replies: a send_nodes packet Send_nodes (response): ``` -[char with a value of 48][Bob's (The reciever's) Public key (client_id) (32 bytes))][Alice's (The sender's) Public key (client_id) (32 bytes)][Random nonce (24 bytes)][Encrypted with the nonce, private key of the sender and public key of the reciever:[char with a value of 49][random 8 byte (ping_id)][Nodes in node format, length=40 * (number of nodes (maximum of 6 nodes)) bytes]] +[char with a value of 48][Bob's (The receiver's) Public key (client_id) (32 bytes))][Alice's (The sender's) Public key (client_id) (32 bytes)][Random nonce (24 bytes)][Encrypted with the nonce, private key of the sender and public key of the receiver:[char with a value of 49][random 8 byte (ping_id)][Nodes in node format, length=40 * (number of nodes (maximum of 6 nodes)) bytes]] ``` Broadcast packet: ``` -[char with a value of 48][Bob's (The reciever's) Public key (client_id) (32 bytes))][Alice's (The sender's) Public key (client_id) (32 bytes)][nonce][Encrypted with the nonce, private key of the sender and public key of the reciever:[char with a value of 50][Data to send to everyone]] +[char with a value of 48][Bob's (The receiver's) Public key (client_id) (32 bytes))][Alice's (The sender's) Public key (client_id) (32 bytes)][nonce][Encrypted with the nonce, private key of the sender and public key of the receiver:[char with a value of 50][Data to send to everyone]] ``` @@ -68,4 +68,4 @@ Ban a peer [uint8_t message[messagelen]] 65 - action (/me) -[uint8_t message[messagelen]] \ No newline at end of file +[uint8_t message[messagelen]] diff --git a/docs/Prevent_Tracking.txt b/docs/Prevent_Tracking.txt index c5f33e96..d170103f 100644 --- a/docs/Prevent_Tracking.txt +++ b/docs/Prevent_Tracking.txt @@ -110,7 +110,8 @@ encrypted with that temporary private key and the nonce and the public key from (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)]] +encrypted with real private key of the sender, the nonce in the data packet and +the real public key of the receiver:[[uint8_t id][data (optional)]] Data sent to us: announce response packet: @@ -153,5 +154,5 @@ 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 * ( +accepted if this number is bigger than the last one received] [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/TCP_Network.txt b/docs/TCP_Network.txt index 775ccc88..9841329c 100644 --- a/docs/TCP_Network.txt +++ b/docs/TCP_Network.txt @@ -81,7 +81,7 @@ received client sent the server the public key and the public key we sent to the client, the next with base nonce + 1...) -The connection is set to an unconfirmed state until a packet is recieved and +The connection is set to an unconfirmed state until a packet is received and decrypted correctly using the information in the handshake. each packet sent to/from the server has an id (the first byte of the plain text @@ -135,7 +135,7 @@ responses must be sent to the proper client. Ping responses must have the same ping_id as the request. -If the server recieves a ping packet he must respond with a ping response. +If the server receives a ping packet he must respond with a ping response. The server will send a ping packet to clients every 30 seconds, they have 30 seconds to respond, if they don't the connection is deleted. diff --git a/docs/av_api.md b/docs/av_api.md index 17930144..2f536ade 100644 --- a/docs/av_api.md +++ b/docs/av_api.md @@ -34,7 +34,7 @@ msi_session_t* - pointer to a newly created msi session handler. ###msi_session_t reference: How to handle msi session: -Controling is done via callbacks and action handlers. +Controlling is done via callbacks and action handlers. First register callbacks for every state/action received and make sure NOT TO PLACE SOMETHING LIKE LOOPS THAT TAKES A LOT OF TIME TO EXECUTE; every callback is being called directly from event loop. You can find examples in phone.c. diff --git a/docs/updates/Crypto.md b/docs/updates/Crypto.md index a6c701d3..939c15e2 100644 --- a/docs/updates/Crypto.md +++ b/docs/updates/Crypto.md @@ -74,4 +74,4 @@ Crypto request packets The encrypted message is encrypted with crypto_box() (using Bobs public key, Alice's private key and the nonce (randomly generated 24 bytes)) and is a message from Alice in which she tells Bob who she is. -Each node can route the request to the reciever if they are connected to him. This is to bypass bad NATs. +Each node can route the request to the receiver if they are connected to him. This is to bypass bad NATs. diff --git a/m4/pkg.m4 b/m4/pkg.m4 index f26f84c9..260e1fb9 100644 --- a/m4/pkg.m4 +++ b/m4/pkg.m4 @@ -53,7 +53,7 @@ fi[]dnl # to PKG_CHECK_MODULES(), but does not set variables or print errors. # # Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) -# only at the first occurence in configure.ac, so if the first place +# only at the first occurrence in configure.ac, so if the first place # it's called might be skipped (such as if it is within an "if", you # have to call PKG_CHECK_EXISTS manually # -------------------------------------------------------------- diff --git a/other/DHTnodes b/other/DHTnodes index 35509931..0abdbbd9 100644 --- a/other/DHTnodes +++ b/other/DHTnodes @@ -1,3 +1,3 @@ -As maintaining 2 seperate lists of the same information seemed redundant, this list has been phased out. +As maintaining 2 separate lists of the same information seemed redundant, this list has been phased out. For a current DHT node list please visit http://wiki.tox.im/nodes diff --git a/other/fun/cracker.c b/other/fun/cracker.c index 9921df31..7b7000de 100644 --- a/other/fun/cracker.c +++ b/other/fun/cracker.c @@ -32,7 +32,7 @@ void print_key(uint8_t *client_id) int main(int argc, char *argv[]) { if (argc < 2) { - printf("usage: ./cracker public_key(or beggining of one in hex format)\n"); + printf("usage: ./cracker public_key(or beginning of one in hex format)\n"); return 0; } diff --git a/toxav/msi.c b/toxav/msi.c index 26e301d3..3ffb44b2 100755 --- a/toxav/msi.c +++ b/toxav/msi.c @@ -206,7 +206,7 @@ static inline__ const uint8_t *stringify_response ( MSIResponse response ) #define ON_HEADER(iterator, header, descriptor, size_const) \ ( memcmp(iterator, descriptor, size_const) == 0){ /* Okay */ \ - iterator += size_const; /* Set iterator at begining of value part */ \ + iterator += size_const; /* Set iterator at beginning of value part */ \ if ( *iterator != value_byte ) { assert(0); return -1; }\ iterator ++;\ uint16_t _value_size = (uint16_t) *(iterator ) << 8 | \ @@ -225,7 +225,7 @@ static inline__ const uint8_t *stringify_response ( MSIResponse response ) * @param msg Container. * @param data The data. * @return int - * @retval -1 Error occured. + * @retval -1 Error occurred. * @retval 0 Success. */ int parse_raw_data ( MSIMessage *msg, const uint8_t *data, uint16_t length ) @@ -338,7 +338,7 @@ void free_message ( MSIMessage *msg ) * @param type Request or response. * @param type_id Type of request/response. * @return MSIMessage* Created message. - * @retval NULL Error occured. + * @retval NULL Error occurred. */ MSIMessage *msi_new_message ( uint8_t type, const uint8_t *type_id ) { @@ -367,7 +367,7 @@ MSIMessage *msi_new_message ( uint8_t type, const uint8_t *type_id ) * * @param data The data. * @return MSIMessage* Parsed message. - * @retval NULL Error occured. + * @retval NULL Error occurred. */ MSIMessage *parse_message ( const uint8_t *data, uint16_t length ) { @@ -422,7 +422,7 @@ uint8_t *append_header_to_string ( *dest = field_byte; /* Set the first byte */ - uint8_t *_getback_byte = dest + 1; /* remeber the byte we were on */ + uint8_t *_getback_byte = dest + 1; /* remember the byte we were on */ dest += 3; /* swith to 4th byte where field value starts */ /* Now set the field value and calculate it's length */ @@ -604,7 +604,7 @@ static inline__ const uint8_t *stringify_error_code ( MSICallError error_code ) * @param msg The message. * @param to Where to. * @return int - * @retval -1 Error occured. + * @retval -1 Error occurred. * @retval 0 Success. */ int send_message ( MSISession *session, MSIMessage *msg, uint32_t to ) @@ -721,7 +721,7 @@ int handle_error ( MSISession *session, MSICallError errid, uint32_t to ) * @param msg The message. * @return int * @retval -1 No error. - * @retval 0 Error occured and response sent. + * @retval 0 Error occurred and response sent. */ int has_call_error ( MSISession *session, MSIMessage *msg ) { @@ -830,7 +830,7 @@ MSICall *init_call ( MSISession *session, int peers, int ringing_timeout ) * * @param session Control session. * @return int - * @retval -1 Error occured. + * @retval -1 Error occurred. * @retval 0 Success. */ int terminate_call ( MSISession *session ) @@ -882,7 +882,7 @@ int handle_recv_invite ( MSISession *session, MSIMessage *msg ) * B calls A. Who has advantage is set bey calculating * 'bigger' Call id and then that call id is being used in * future. User with 'bigger' Call id has the advantage - * as in he will wait the reponse from the other. + * as in he will wait the response from the other. */ if ( call_id_bigger (session->call->id, msg->callid.header_value) == 1 ) { /* Peer has advantage */ @@ -1250,7 +1250,7 @@ void msi_register_callback ( MSICallback callback, MSICallbackID id, void* userd * @param messenger Tox* object. * @param user_agent User agent, i.e. 'Venom'; 'QT-gui' * @return MSISession* The created session. - * @retval NULL Error occured. + * @retval NULL Error occurred. */ MSISession *msi_init_session ( Messenger* messenger ) { @@ -1351,7 +1351,7 @@ int msi_invite ( MSISession *session, MSICallType call_type, uint32_t rngsec, ui * * @param session Control session. * @return int - * @retval -1 Error occured. + * @retval -1 Error occurred. * @retval 0 Success. */ int msi_hangup ( MSISession *session ) @@ -1485,4 +1485,4 @@ int msi_stopcall ( MSISession *session ) terminate_call ( session ); return 0; -} \ No newline at end of file +} diff --git a/toxav/msi.h b/toxav/msi.h index 37fc07a3..39a9c792 100755 --- a/toxav/msi.h +++ b/toxav/msi.h @@ -82,7 +82,7 @@ typedef struct _MSICall { /* Call info structure */ int ringing_timer_id; /* Timer id for ringing timeout */ pthread_mutex_t mutex; /* It's to be assumed that call will have - * seperate thread so add mutex + * separate thread so add mutex */ uint32_t *peers; uint16_t peer_count; @@ -152,7 +152,7 @@ void msi_register_callback(MSICallback callback, MSICallbackID id, void* userdat * * @param messenger Tox* object. * @return MSISession* The created session. - * @retval NULL Error occured. + * @retval NULL Error occurred. */ MSISession *msi_init_session ( Messenger *messenger ); @@ -183,7 +183,7 @@ int msi_invite ( MSISession *session, MSICallType call_type, uint32_t rngsec, ui * * @param session Control session. * @return int - * @retval -1 Error occured. + * @retval -1 Error occurred. * @retval 0 Success. */ int msi_hangup ( MSISession *session ); diff --git a/toxav/phone.c b/toxav/phone.c index 2b33f7e9..74f743f7 100755 --- a/toxav/phone.c +++ b/toxav/phone.c @@ -5,7 +5,7 @@ * This file is for testing/reference purposes only, hence * it is _poorly_ designed and it does not fully reflect the * quaility of msi nor rtp. Although toxmsi* and toxrtp* are tested - * there is always possiblity of crashes. If crash occures, + * there is always possibility of crashes. If crash occures, * contact me ( mannol ) on either irc channel #tox-dev @ freenode.net:6667 * or eniz_vukovic@hotmail.com * @@ -612,7 +612,7 @@ void *decode_video_thread(void *arg) } //else { - /* TODO: request the sender to create a new i-frame immediatly */ + /* TODO: request the sender to create a new i-frame immediately */ //printf("Bad video packet\n"); //} //} diff --git a/toxcore/DHT.c b/toxcore/DHT.c index 1089e2ff..ad496f7d 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c @@ -164,7 +164,7 @@ void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, uint8_t *secr } /* Copy shared_key to decrypt DHT packet from client_id into shared_key - * for packets that we recieve. + * for packets that we receive. */ void DHT_get_shared_key_recv(DHT *dht, uint8_t *shared_key, uint8_t *client_id) { @@ -600,7 +600,7 @@ static int replace_possible_bad( Client_data *list, sort_list(list, length, comp_client_id); - /* TODO: decide if the folowing lines should stay commented or not. + /* TODO: decide if the following lines should stay commented or not. if (id_closest(comp_client_id, list[0].client_id, client_id) == 1) return 0;*/ @@ -861,20 +861,20 @@ static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cli uint64_t temp_time = unix_time(); memcpy(plain_message, &temp_time, sizeof(temp_time)); - Node_format reciever; - memcpy(reciever.client_id, public_key, CLIENT_ID_SIZE); - reciever.ip_port = ip_port; - memcpy(plain_message + sizeof(temp_time), &reciever, sizeof(reciever)); + Node_format receiver; + memcpy(receiver.client_id, public_key, CLIENT_ID_SIZE); + receiver.ip_port = ip_port; + memcpy(plain_message + sizeof(temp_time), &receiver, sizeof(receiver)); if (sendback_node != NULL) - memcpy(plain_message + sizeof(temp_time) + sizeof(reciever), sendback_node, sizeof(Node_format)); + memcpy(plain_message + sizeof(temp_time) + sizeof(receiver), sendback_node, sizeof(Node_format)); else - memset(plain_message + sizeof(temp_time) + sizeof(reciever), 0, sizeof(Node_format)); + memset(plain_message + sizeof(temp_time) + sizeof(receiver), 0, sizeof(Node_format)); int len_m = encrypt_data_symmetric(dht->secret_symmetric_key, nonce, plain_message, - sizeof(temp_time) + sizeof(reciever) + sizeof(Node_format), + sizeof(temp_time) + sizeof(receiver) + sizeof(Node_format), encrypted_message + crypto_secretbox_NONCEBYTES); if (len_m != NODES_ENCRYPTED_MESSAGE_LENGTH - crypto_secretbox_NONCEBYTES) diff --git a/toxcore/DHT.h b/toxcore/DHT.h index 3d2722f8..81f1f560 100644 --- a/toxcore/DHT.h +++ b/toxcore/DHT.h @@ -192,7 +192,7 @@ typedef struct { void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, uint8_t *secret_key, uint8_t *client_id); /* Copy shared_key to decrypt DHT packet from client_id into shared_key - * for packets that we recieve. + * for packets that we receive. */ void DHT_get_shared_key_recv(DHT *dht, uint8_t *shared_key, uint8_t *client_id); diff --git a/toxcore/Lossless_UDP.c b/toxcore/Lossless_UDP.c index c0db8a10..9a7cdcb2 100644 --- a/toxcore/Lossless_UDP.c +++ b/toxcore/Lossless_UDP.c @@ -292,7 +292,7 @@ static int new_inconnection(Lossless_UDP *ludp, IP_Port ip_port) } /* - * return an integer corresponding to the next connection in our incoming connection list with at least numpackets in the recieve queue. + * return an integer corresponding to the next connection in our incoming connection list with at least numpackets in the receive queue. * return -1 if there are no new incoming connections in the list. */ int incoming_connection(Lossless_UDP *ludp, uint32_t numpackets) diff --git a/toxcore/Lossless_UDP.h b/toxcore/Lossless_UDP.h index b23d602a..01ce05f9 100644 --- a/toxcore/Lossless_UDP.h +++ b/toxcore/Lossless_UDP.h @@ -156,7 +156,7 @@ int new_connection(Lossless_UDP *ludp, IP_Port ip_port); int getconnection_id(Lossless_UDP *ludp, IP_Port ip_port); /* - * return an integer corresponding to the next connection in our incoming connection list with at least numpackets in the recieve queue. + * return an integer corresponding to the next connection in our incoming connection list with at least numpackets in the receive queue. * return -1 if there are no new incoming connections in the list. */ int incoming_connection(Lossless_UDP *ludp, uint32_t numpackets); diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index db5390c0..752b164d 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -2172,7 +2172,7 @@ void do_friends(Messenger *m) } if (m->friendlist[i].ping_lastrecv + FRIEND_CONNECTION_TIMEOUT < temp_time) { - /* If we stopped recieving ping packets, kill it. */ + /* If we stopped receiving ping packets, kill it. */ crypto_kill(m->net_crypto, m->friendlist[i].crypt_connection_id); m->friendlist[i].crypt_connection_id = -1; set_friend_status(m, i, FRIEND_CONFIRMED); diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index c29b6594..43cc48f9 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -90,7 +90,7 @@ enum { /* Interval between the sending of ping packets. */ #define FRIEND_PING_INTERVAL 5 -/* If no packets are recieved from friend in this time interval, kill the connection. */ +/* If no packets are received from friend in this time interval, kill the connection. */ #define FRIEND_CONNECTION_TIMEOUT (FRIEND_PING_INTERVAL * 2) /* USERSTATUS - @@ -354,7 +354,7 @@ int setname(Messenger *m, uint8_t *name, uint16_t length); /* * Get your nickname. - * m - The messanger context to use. + * m - The messenger context to use. * name needs to be a valid memory location with a size of at least MAX_NAME_LENGTH bytes. * * return length of the name. diff --git a/toxcore/TCP_server.c b/toxcore/TCP_server.c index 410111f4..7ad5ff7e 100644 --- a/toxcore/TCP_server.c +++ b/toxcore/TCP_server.c @@ -224,7 +224,7 @@ int read_TCP_packet(sock_t sock, uint8_t *data, uint16_t length) return -1; } -/* return length of recieved packet on success. +/* return length of received packet on success. * return 0 if could not read any packet. * return -1 on failure (connection must be killed). */ diff --git a/toxcore/TCP_server.h b/toxcore/TCP_server.h index 498b1147..5046b8eb 100644 --- a/toxcore/TCP_server.h +++ b/toxcore/TCP_server.h @@ -140,7 +140,7 @@ uint16_t read_TCP_length(sock_t sock); */ int read_TCP_packet(sock_t sock, uint8_t *data, uint16_t length); -/* return length of recieved packet on success. +/* return length of received packet on success. * return 0 if could not read any packet. * return -1 on failure (connection must be killed). */ diff --git a/toxcore/assoc.c b/toxcore/assoc.c index 2c1f0bad..50bc3a3e 100644 --- a/toxcore/assoc.c +++ b/toxcore/assoc.c @@ -28,7 +28,7 @@ * Candidates are kept in buckets of hash tables. The hash * function is calculated from the client_id. Up to * HASH_COLLIDE_COUNT alternative positions are tried if - * the inital position is already used by a different entry. + * the initial position is already used by a different entry. * The collision function is multiplicative, not additive. * * A new candidate can bump an existing candidate, if it is diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 17d2e8ff..6e5b8c82 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -284,7 +284,7 @@ int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uin /* Create a request to peer. * send_public_key and send_secret_key are the pub/secret keys of the sender. - * recv_public_key is public key of reciever. + * recv_public_key is public key of receiver. * packet must be an array of MAX_DATA_SIZE big. * Data represents the data we send with the request with length being the length of the data. * request_id is the id of the request (32 = friend request, 254 = ping request). diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index da776527..86668058 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -162,7 +162,7 @@ int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uin /* Create a request to peer. * send_public_key and send_secret_key are the pub/secret keys of the sender. - * recv_public_key is public key of reciever. + * recv_public_key is public key of receiver. * packet must be an array of MAX_DATA_SIZE big. * Data represents the data we send with the request with length being the length of the data. * request_id is the id of the request (32 = friend request, 254 = ping request). diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index 329b1d13..c9f60b2b 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c @@ -513,9 +513,9 @@ static int handle_fakeid_announce(void *object, uint8_t *source_pubkey, uint8_t return 0; } /* Send data of length length to friendnum. - * This data will be recieved by the friend using the Onion_Data_Handlers callbacks. + * This data will be received by the friend using the Onion_Data_Handlers callbacks. * - * Even if this function succeeds, the friend might not recieve any data. + * Even if this function succeeds, the friend might not receive any data. * * return the number of packets sent on success * return -1 on failure. @@ -578,7 +578,7 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, uint8_t *data, uint32 /* Try to send the fakeid via the DHT instead of onion * - * Even if this function succeeds, the friend might not recieve any data. + * Even if this function succeeds, the friend might not receive any data. * * return the number of packets sent on success * return -1 on failure. diff --git a/toxcore/onion_client.h b/toxcore/onion_client.h index 4045cc0e..9c89afe5 100644 --- a/toxcore/onion_client.h +++ b/toxcore/onion_client.h @@ -172,9 +172,9 @@ int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port); /* Send data of length length to friendnum. - * This data will be recieved by the friend using the Onion_Data_Handlers callbacks. + * This data will be received by the friend using the Onion_Data_Handlers callbacks. * - * Even if this function succeeds, the friend might not recieve any data. + * Even if this function succeeds, the friend might not receive any data. * * return the number of packets sent on success * return -1 on failure. diff --git a/toxcore/tox.c b/toxcore/tox.c index c07473dd..ec21407f 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -186,7 +186,7 @@ int tox_set_name(Tox *tox, uint8_t *name, uint16_t length) } /* Get your nickname. - * m - The messanger context to use. + * m - The messenger context to use. * name - Pointer to a string for the name. (must be at least MAX_NAME_LENGTH) * * return length of the name. diff --git a/toxcore/tox.h b/toxcore/tox.h index d94c0e13..c344d366 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -210,7 +210,7 @@ int tox_set_name(Tox *tox, uint8_t *name, uint16_t length); /* * Get your nickname. - * m - The messanger context to use. + * m - The messenger context to use. * name - needs to be a valid memory location with a size of at least MAX_NAME_LENGTH (128) bytes. * * return length of name. @@ -515,11 +515,11 @@ uint32_t tox_get_chatlist(Tox *tox, int *out_list, uint32_t list_size); * tox_file_data_remaining(...) can be used to know how many bytes are left to send/receive. * * If the connection breaks during file sending (The other person goes offline without pausing the sending and then comes back) - * the reciever must send a control packet with receive_send == 0 message_id = TOX_FILECONTROL_RESUME_BROKEN and the data being - * a uint64_t (in host byte order) containing the number of bytes recieved. + * the receiver must send a control packet with receive_send == 0 message_id = TOX_FILECONTROL_RESUME_BROKEN and the data being + * a uint64_t (in host byte order) containing the number of bytes received. * - * If the sender recieves this packet, he must send a control packet with receive_send == 1 and control_type == TOX_FILECONTROL_ACCEPT - * then he must start sending file data from the position (data , uint64_t in host byte order) recieved in the TOX_FILECONTROL_RESUME_BROKEN packet. + * If the sender receives this packet, he must send a control packet with receive_send == 1 and control_type == TOX_FILECONTROL_ACCEPT + * then he must start sending file data from the position (data , uint64_t in host byte order) received in the TOX_FILECONTROL_RESUME_BROKEN packet. * * More to come... */ From de079d7cf78c7cc6888aa604c319a736d01f7326 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Wed, 16 Apr 2014 13:53:51 -0400 Subject: [PATCH 012/117] Some speedups and small fixes. --- auto_tests/tox_test.c | 7 ++++--- toxcore/onion_client.c | 14 +++++++++++++- toxcore/ping.c | 16 +++++++++++----- 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c index 1e01aee7..13c4fc7b 100644 --- a/auto_tests/tox_test.c +++ b/auto_tests/tox_test.c @@ -110,7 +110,7 @@ void write_file(Tox *m, int friendnumber, uint8_t filenumber, uint8_t *data, uin START_TEST(test_few_clients) { - long long unsigned int cur_time = time(NULL); + long long unsigned int con_time, cur_time = time(NULL); Tox *tox1 = tox_new(TOX_ENABLE_IPV6_DEFAULT); Tox *tox2 = tox_new(TOX_ENABLE_IPV6_DEFAULT); Tox *tox3 = tox_new(TOX_ENABLE_IPV6_DEFAULT); @@ -131,6 +131,7 @@ START_TEST(test_few_clients) if (tox_isconnected(tox1) && tox_isconnected(tox2) && tox_isconnected(tox3) && off) { printf("Toxes are online, took %llu seconds\n", time(NULL) - cur_time); + con_time = time(NULL); off = 0; } @@ -141,7 +142,7 @@ START_TEST(test_few_clients) c_sleep(50); } - printf("tox clients connected\n"); + printf("tox clients connected took %llu seconds\n", time(NULL) - con_time); to_compare = 974536; tox_callback_friend_message(tox3, print_message, &to_compare); tox_send_message(tox2, 0, (uint8_t *)"Install Gentoo", sizeof("Install Gentoo")); @@ -331,7 +332,7 @@ Suite *tox_suite(void) Suite *s = suite_create("Tox"); DEFTESTCASE_SLOW(few_clients, 50); - DEFTESTCASE_SLOW(many_clients, 300); + DEFTESTCASE_SLOW(many_clients, 150); return s; } diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index ca3ec560..4a5a37d2 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c @@ -286,7 +286,7 @@ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, uint8_t *publ list_nodes[index].is_stored = is_stored; list_nodes[index].timestamp = unix_time(); - list_nodes[index].last_pinged = unix_time(); + list_nodes[index].last_pinged = 0; list_nodes[index].path_used = set_path_timeouts(onion_c, num, source); return 0; } @@ -863,6 +863,11 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum) ++count; + if (list_nodes[i].last_pinged == 0) { + list_nodes[i].last_pinged = unix_time(); + continue; + } + 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) == 0) { list_nodes[i].last_pinged = unix_time(); @@ -931,6 +936,13 @@ static void do_announce(Onion_Client *onion_c) continue; ++count; + + /* Don't announce ourselves the first time this is run to new peers */ + if (list_nodes[i].last_pinged == 0) { + list_nodes[i].last_pinged = 1; + continue; + } + uint32_t interval = ANNOUNCE_INTERVAL_NOT_ANNOUNCED; if (list_nodes[i].is_stored) { diff --git a/toxcore/ping.c b/toxcore/ping.c index 649d3fff..e43c3b1a 100644 --- a/toxcore/ping.c +++ b/toxcore/ping.c @@ -38,10 +38,10 @@ #define PING_NUM_MAX 512 /* Maximum newly announced nodes to ping per TIME_TO_PING seconds. */ -#define MAX_TO_PING 16 +#define MAX_TO_PING 8 /* Ping newly announced nodes to ping per TIME_TO_PING seconds*/ -#define TIME_TO_PING 5 +#define TIME_TO_PING 3 typedef struct { IP_Port ip_port; @@ -300,12 +300,18 @@ int add_to_ping(PING *ping, uint8_t *client_id, IP_Port ip_port) ipport_copy(&ping->to_ping[i].ip_port, &ip_port); return 0; } + + if (memcmp(ping->to_ping[i].client_id, client_id, CLIENT_ID_SIZE) == 0) { + return -1; + } } + uint32_t r = rand(); + for (i = 0; i < MAX_TO_PING; ++i) { - if (id_closest(ping->dht->self_public_key, ping->to_ping[i].client_id, client_id) == 2) { - memcpy(ping->to_ping[i].client_id, client_id, CLIENT_ID_SIZE); - ipport_copy(&ping->to_ping[i].ip_port, &ip_port); + if (id_closest(ping->dht->self_public_key, ping->to_ping[(i + r) % MAX_TO_PING].client_id, client_id) == 2) { + memcpy(ping->to_ping[(i + r) % MAX_TO_PING].client_id, client_id, CLIENT_ID_SIZE); + ipport_copy(&ping->to_ping[(i + r) % MAX_TO_PING].ip_port, &ip_port); return 0; } } From 47fb2e8067429c3ad142e9375ce2c5469218ad96 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 17 Apr 2014 20:53:12 -0400 Subject: [PATCH 013/117] Fixed build issues. --- toxcore/TCP_client.c | 3 +++ toxcore/TCP_server.c | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c index b69b422e..4f3411f1 100644 --- a/toxcore/TCP_client.c +++ b/toxcore/TCP_client.c @@ -20,6 +20,9 @@ * */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif #include "TCP_client.h" diff --git a/toxcore/TCP_server.c b/toxcore/TCP_server.c index 410111f4..1c4ffdcb 100644 --- a/toxcore/TCP_server.c +++ b/toxcore/TCP_server.c @@ -20,6 +20,10 @@ * */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "TCP_server.h" #if !defined(_WIN32) && !defined(__WIN32__) && !defined (WIN32) From 9f6b17de55a31cf7aeb8370345849c30683f0c0c Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 18 Apr 2014 20:36:52 -0400 Subject: [PATCH 014/117] Added function to increment nonce by specified number. Nonces now behave like big endian numbers. --- toxcore/net_crypto.c | 32 ++++++++++++++++++++++++++++---- toxcore/net_crypto.h | 3 +++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 17d2e8ff..ae3a69a1 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -163,16 +163,40 @@ void increment_nonce(uint8_t *nonce) { uint32_t i; - for (i = 0; i < crypto_box_NONCEBYTES; ++i) { - ++nonce[i]; + for (i = crypto_box_NONCEBYTES; i != 0; --i) { + ++nonce[i - 1]; - if (nonce[i] != 0) + if (nonce[i - 1] != 0) break; } } +/* increment the given nonce by num */ +void increment_nonce_number(uint8_t *nonce, uint32_t num) +{ + uint32_t num1, num2; + memcpy(&num1, nonce + (crypto_box_NONCEBYTES - sizeof(num1)), sizeof(num1)); + num1 = ntohl(num1); + num2 = num + num1; + + if (num2 < num1) { + uint32_t i; + + for (i = crypto_box_NONCEBYTES - sizeof(num1); i != 0; --i) { + ++nonce[i - 1]; + + if (nonce[i - 1] != 0) + break; + } + } + + num2 = htonl(num2); + memcpy(nonce + (crypto_box_NONCEBYTES - sizeof(num2)), &num2, sizeof(num2)); +} #if crypto_box_NONCEBYTES != crypto_secretbox_NONCEBYTES -/*if they no longer equal each other, this function must be split into two.*/ +/*if they no longer equal each other, this function and the previous ones + *must be split into two. + */ #error random_nonce(): crypto_box_NONCEBYTES must equal crypto_secretbox_NONCEBYTES. #endif /* Fill the given nonce with random bytes. */ diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index da776527..3c70c4d3 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -135,6 +135,9 @@ int decrypt_data_symmetric(uint8_t *secret_key, uint8_t *nonce, uint8_t *encrypt /* Increment the given nonce by 1. */ void increment_nonce(uint8_t *nonce); +/* increment the given nonce by num */ +void increment_nonce_number(uint8_t *nonce, uint32_t num); + /* Fill the given nonce with random bytes. */ void random_nonce(uint8_t *nonce); From db3672bf3f3b8d2f04ba82c82f769732213cf685 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 18 Apr 2014 22:00:12 -0400 Subject: [PATCH 015/117] Added text document explaining what needs to be done before TCP can be merged. --- docs/Tox_middle_level_network_protocol.txt | 41 ++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 docs/Tox_middle_level_network_protocol.txt diff --git a/docs/Tox_middle_level_network_protocol.txt b/docs/Tox_middle_level_network_protocol.txt new file mode 100644 index 00000000..ae0fd0f6 --- /dev/null +++ b/docs/Tox_middle_level_network_protocol.txt @@ -0,0 +1,41 @@ +The TCP client and TCP server part are in a state that can be considered +feature complete. Why doesn't Tox support TCP yet even if those parts are +complete? + +The answer is that a way to ensure a smooth switchover between the TCP and UDP +needs to be added. If Tox first connects to the other user using TCP but then +due to pure chance manages to connect using the faster direct UDP connection +Tox must switch seamlessly from the TCP to the UDP connection without there +being any data loss or the other user going offline and then back online. The +transition must be seamless whatever both connected users are doing be it +transferring files or simply chatting together. + +Possible evil/bad or simply TCP relays going offline must not impact the +connection between both clients. + +Typically Tox will use more than one TCP relay to connect to other peers for +maximum connection stability which means there must be a way for Tox to take +advantage of multiple relays in a way that the user will never be aware if one +of them goes offline/tries to slow down the connection/decides to corrupt +packets/etc.. + +To accomplish this Tox needs something between the low level protocol (TCP) and +high level Tox messaging protocol hence the name middle level. + +The plan is to move some functionality from lossless_UDP to a higher level: +more specifically the functionality for detecting which packets a peer is +missing and the ability to request and send them again. lossless UDP uses plain +text packets to request missing packets from the other peer while Tox is +currently designed to kill the connection if any packet tampering is detected. +This works very well when connecting directly with someone because if the +attacker can modify packets it means he can kill your connection anyways. With +TCP relays however that is not the case as such the packets used to request +missing packets must be encrypted. If it is detected that a packet has been +tampered, the connection must stay intact while the evil relay must be +disconnected from and replaced with a good relay, the behavior must be the same +as if the relay had just suddenly gone online. Of course something to protect +from evil "friends" framing relays must also be implemented. + +Detailed implementation details: + +Coming soon. From 39ac20fc2daa6a291da9f1fd85735596d684490c Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 19 Apr 2014 11:28:46 -0400 Subject: [PATCH 016/117] Fixed possible pointer issues. --- toxcore/Messenger.c | 5 +++-- toxcore/util.c | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index db5390c0..6bfe4d9b 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -2733,12 +2733,13 @@ static int messenger_load_state_callback(void *outer, uint8_t *data, uint32_t le /* Load the messenger from data of size length. */ int messenger_load(Messenger *m, uint8_t *data, uint32_t length) { - uint32_t cookie_len = 2 * sizeof(uint32_t); + uint32_t data32[2]; + uint32_t cookie_len = sizeof(data32); if (length < cookie_len) return -1; - uint32_t *data32 = (uint32_t *)data; + memcpy(data32, data, sizeof(data32)); if (!data32[0] && (data32[1] == MESSENGER_STATE_COOKIE_GLOBAL)) return load_state(messenger_load_state_callback, m, data + cookie_len, diff --git a/toxcore/util.c b/toxcore/util.c index d56c446e..44f24f58 100644 --- a/toxcore/util.c +++ b/toxcore/util.c @@ -99,11 +99,11 @@ int load_state(load_state_callback_func load_state_callback, void *outer, uint16_t type; uint32_t length_sub, cookie_type; - uint32_t size32 = sizeof(uint32_t), size_head = size32 * 2; + uint32_t size_head = sizeof(uint32_t) * 2; while (length >= size_head) { - length_sub = *(uint32_t *)data; - cookie_type = *(uint32_t *)(data + size32); + memcpy(&length_sub, data, sizeof(length_sub)); + memcpy(&cookie_type, data + sizeof(length_sub), sizeof(cookie_type)); data += size_head; length -= size_head; From 98bea094b38784281f784073051db6b4e1be2597 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 19 Apr 2014 11:38:14 -0400 Subject: [PATCH 017/117] Autoconf apparently gives us a nice define for processor endianess. --- toxcore/util.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/toxcore/util.c b/toxcore/util.c index 44f24f58..07db57f0 100644 --- a/toxcore/util.c +++ b/toxcore/util.c @@ -67,22 +67,17 @@ uint32_t id_copy(uint8_t *dest, uint8_t *src) void host_to_net(uint8_t *num, uint16_t numbytes) { - union { - uint32_t i; - uint8_t c[4]; - } a; - a.i = 1; +#ifndef WORDS_BIGENDIAN + uint32_t i; + uint8_t buff[numbytes]; - 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); + for (i = 0; i < numbytes; ++i) { + buff[i] = num[numbytes - i - 1]; } + + memcpy(num, buff, numbytes); +#endif + return; } /* state load/save */ From 235ce5685559e2cd64de96d0d2ac1aeafe86aeb5 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 19 Apr 2014 16:18:07 -0400 Subject: [PATCH 018/117] Fixed possible buffer overflow in function to send friend requests. --- toxcore/friend_requests.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toxcore/friend_requests.c b/toxcore/friend_requests.c index 469ab02d..e879d64c 100644 --- a/toxcore/friend_requests.c +++ b/toxcore/friend_requests.c @@ -37,7 +37,7 @@ */ 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) + if (length + sizeof(nospam_num) >= MAX_DATA_SIZE) return -1; uint8_t temp[MAX_DATA_SIZE]; From 8815956f0a77e0caf506cd730e6ae18d5091b782 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 19 Apr 2014 16:52:29 -0400 Subject: [PATCH 019/117] Small cleanups. --- toxcore/friend_requests.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/toxcore/friend_requests.c b/toxcore/friend_requests.c index e879d64c..82e51a76 100644 --- a/toxcore/friend_requests.c +++ b/toxcore/friend_requests.c @@ -135,20 +135,17 @@ int remove_request_received(Friend_Requests *fr, uint8_t *client_id) static int friendreq_handlepacket(void *object, uint8_t *source_pubkey, uint8_t *packet, uint32_t length) { - if (length == 0) + Friend_Requests *fr = object; + + if (length <= 1 + sizeof(fr->nospam)) return 1; ++packet; --length; - Friend_Requests *fr = object; - if (fr->handle_friendrequest_isset == 0) return 1; - if (length <= sizeof(fr->nospam)) - return 1; - if (request_received(fr, source_pubkey)) return 1; @@ -161,11 +158,12 @@ static int friendreq_handlepacket(void *object, uint8_t *source_pubkey, uint8_t addto_receivedlist(fr, source_pubkey); - uint8_t message[length - 4 + 1]; - memcpy(message, packet + 4, length - 4); + uint32_t message_len = length - sizeof(fr->nospam); + uint8_t message[message_len + 1]; + memcpy(message, packet + sizeof(fr->nospam), message_len); message[sizeof(message) - 1] = 0; /* Be sure the message is null terminated. */ - (*fr->handle_friendrequest)(fr->handle_friendrequest_object, source_pubkey, message, length - 4, + (*fr->handle_friendrequest)(fr->handle_friendrequest_object, source_pubkey, message, message_len, fr->handle_friendrequest_userdata); return 0; } From 09d9d34a9300a7aab59ccde74a72cd54f4672599 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 19 Apr 2014 17:50:10 -0400 Subject: [PATCH 020/117] Removed deprecated function from public api. Added upper length check to friendreq_handlepacket(). --- toxcore/friend_requests.c | 2 +- toxcore/tox.c | 11 ----------- toxcore/tox.h | 37 ------------------------------------- 3 files changed, 1 insertion(+), 49 deletions(-) diff --git a/toxcore/friend_requests.c b/toxcore/friend_requests.c index 82e51a76..c5cfa4b4 100644 --- a/toxcore/friend_requests.c +++ b/toxcore/friend_requests.c @@ -137,7 +137,7 @@ static int friendreq_handlepacket(void *object, uint8_t *source_pubkey, uint8_t { Friend_Requests *fr = object; - if (length <= 1 + sizeof(fr->nospam)) + if (length <= 1 + sizeof(fr->nospam) || length > MAX_DATA_SIZE) return 1; ++packet; diff --git a/toxcore/tox.c b/toxcore/tox.c index c07473dd..d78ef091 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -739,17 +739,6 @@ uint64_t tox_file_data_remaining(Tox *tox, int32_t friendnumber, uint8_t filenum /***************END OF FILE SENDING FUNCTIONS******************/ -/* Use these functions to bootstrap the client. - * Sends a get nodes request to the given node with ip port and public_key. - */ -void tox_bootstrap_from_ip(Tox *tox, tox_IP_Port _ip_port, uint8_t *public_key) -{ - Messenger *m = tox; - IP_Port ip_port; - memcpy(&ip_port, &_ip_port, sizeof(IP_Port)); - DHT_bootstrap(m->dht, ip_port, public_key); -} - int tox_bootstrap_from_address(Tox *tox, const char *address, uint8_t ipv6enabled, uint16_t port, uint8_t *public_key) { diff --git a/toxcore/tox.h b/toxcore/tox.h index d94c0e13..fadd1a28 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -601,43 +601,6 @@ uint64_t tox_file_data_remaining(Tox *tox, int32_t friendnumber, uint8_t filenum /***************END OF FILE SENDING FUNCTIONS******************/ -/* WARNING: DEPRECATED, DO NOT USE. */ -typedef union { - uint8_t c[4]; - uint16_t s[2]; - uint32_t i; -} tox_IP4; - -typedef union { - uint8_t uint8[16]; - uint16_t uint16[8]; - uint32_t uint32[4]; - struct in6_addr in6_addr; -} tox_IP6; - -typedef struct { - uint8_t family; - /* Not used for anything right now. */ - uint8_t padding[3]; - union { - tox_IP4 ip4; - tox_IP6 ip6; - }; -} tox_IP; - -/* will replace IP_Port as soon as the complete infrastructure is in place - * removed the unused union and padding also */ -typedef struct { - tox_IP ip; - uint16_t port; -} tox_IP_Port; -/* WARNING: DEPRECATED, DO NOT USE. */ -/* Sends a "get nodes" request to the given node with ip, port and public_key - * to setup connections - */ -void tox_bootstrap_from_ip(Tox *tox, tox_IP_Port ip_port, uint8_t *public_key); - - /* * Use this function to bootstrap the client. */ From 1603ca974eae3fe0d94b597103f04acfb96fcab0 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sun, 20 Apr 2014 20:17:24 -0400 Subject: [PATCH 021/117] Small cleanup. --- toxcore/Messenger.c | 4 ++-- toxcore/Messenger.h | 7 ++----- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 6bfe4d9b..eb08fb94 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -689,7 +689,7 @@ static int send_user_istyping(Messenger *m, int32_t friendnumber, uint8_t is_typ static int send_ping(Messenger *m, int32_t friendnumber) { - int ret = write_cryptpacket_id(m, friendnumber, PACKET_ID_PING, 0, 0); + int ret = write_cryptpacket_id(m, friendnumber, PACKET_ID_ALIVE, 0, 0); if (ret == 1) m->friendlist[friendnumber].ping_lastsent = unix_time(); @@ -1928,7 +1928,7 @@ void do_friends(Messenger *m) uint32_t data_length = len - 1; switch (packet_id) { - case PACKET_ID_PING: { + case PACKET_ID_ALIVE: { m->friendlist[i].ping_lastrecv = temp_time; break; } diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index c29b6594..c6d89fac 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -38,7 +38,8 @@ #define FRIEND_ADDRESS_SIZE (crypto_box_PUBLICKEYBYTES + sizeof(uint32_t) + sizeof(uint16_t)) -#define PACKET_ID_PING 0 +/* NOTE: Packet ids below 16 must never be used. */ +#define PACKET_ID_ALIVE 16 #define PACKET_ID_NICKNAME 48 #define PACKET_ID_STATUSMESSAGE 49 #define PACKET_ID_USERSTATUS 50 @@ -80,10 +81,6 @@ enum { FAERR_NOMEM = -8 }; -/* Don't assume MAX_STATUSMESSAGE_LENGTH will stay at 128, it may be increased - * to an absurdly large number later. - */ - /* Default start timeout in seconds between friend requests. */ #define FRIENDREQUEST_TIMEOUT 5; From 9c6a8432ce7298766669d1e6a966b5493971afb7 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Mon, 21 Apr 2014 16:51:36 -0400 Subject: [PATCH 022/117] Crypto related cleanups. Moved Bunch of functions from net_crypto to crypto_core. decrypt_data_fast and decrypt_data_symmetric were the same thing therefore, removed decrypt_data_fast. Replaced all the crypto_secretbox_* defines with the equivalent crypto_box_* one. New define: crypto_box_KEYBYTES that is equal to crypto_box_BEFORENMBYTES. --- auto_tests/TCP_test.c | 8 +- auto_tests/crypto_test.c | 22 ++-- testing/crypto_speed_test.c | 4 +- toxav/msi.c | 32 +++--- toxav/rtp.c | 40 ++++---- toxcore/DHT.c | 18 ++-- toxcore/DHT.h | 2 +- toxcore/Makefile.inc | 2 + toxcore/Messenger.c | 69 ------------- toxcore/Messenger.h | 18 ---- toxcore/TCP_client.c | 6 +- toxcore/TCP_client.h | 2 +- toxcore/TCP_server.c | 8 +- toxcore/TCP_server.h | 2 +- toxcore/crypto_core.c | 168 ++++++++++++++++++++++++++++++ toxcore/crypto_core.h | 86 ++++++++++++++++ toxcore/friend_requests.h | 2 - toxcore/group_chats.c | 3 +- toxcore/group_chats.h | 2 - toxcore/net_crypto.c | 200 +----------------------------------- toxcore/net_crypto.h | 66 ------------ toxcore/network.h | 5 +- toxcore/onion.c | 40 ++++---- toxcore/onion.h | 8 +- toxcore/onion_announce.c | 14 +-- toxcore/onion_announce.h | 6 +- toxcore/onion_client.c | 8 +- toxcore/onion_client.h | 2 +- toxcore/ping.c | 8 +- toxcore/tox.c | 32 +----- toxcore/tox.h | 26 ----- 31 files changed, 377 insertions(+), 532 deletions(-) create mode 100644 toxcore/crypto_core.c create mode 100644 toxcore/crypto_core.h diff --git a/auto_tests/TCP_test.c b/auto_tests/TCP_test.c index ff30e8f6..d0470d29 100644 --- a/auto_tests/TCP_test.c +++ b/auto_tests/TCP_test.c @@ -89,7 +89,7 @@ START_TEST(test_basic) uint8_t r_req[2 + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES]; uint16_t size = 1 + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES; size = htons(size); - ret = encrypt_data_fast(f_shared_key, f_nonce, r_req_p, 1 + crypto_box_PUBLICKEYBYTES, r_req + 2); + ret = encrypt_data_symmetric(f_shared_key, f_nonce, r_req_p, 1 + crypto_box_PUBLICKEYBYTES, r_req + 2); increment_nonce(f_nonce); memcpy(r_req, &size, 2); uint32_t i; @@ -110,7 +110,7 @@ START_TEST(test_basic) memcpy(&size, packet_resp, 2); ck_assert_msg(ntohs(size) == 2 + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES, "Wrong packet size."); uint8_t packet_resp_plain[4096]; - ret = decrypt_data_fast(f_shared_key, f_nonce_r, packet_resp + 2, recv_data_len - 2, packet_resp_plain); + ret = decrypt_data_symmetric(f_shared_key, f_nonce_r, packet_resp + 2, recv_data_len - 2, packet_resp_plain); ck_assert_msg(ret != -1, "decryption failed"); increment_nonce(f_nonce_r); ck_assert_msg(packet_resp_plain[0] == 1, "wrong packet id %u", packet_resp_plain[0]); @@ -179,7 +179,7 @@ int write_packet_TCP_secure_connection(struct sec_TCP_con *con, uint8_t *data, u uint16_t c_length = htons(length + crypto_box_MACBYTES); memcpy(packet, &c_length, sizeof(uint16_t)); - int len = encrypt_data_fast(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t)); + int len = encrypt_data_symmetric(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t)); if ((unsigned int)len != (sizeof(packet) - sizeof(uint16_t))) return -1; @@ -194,7 +194,7 @@ int read_packet_sec_TCP(struct sec_TCP_con *con, uint8_t *data, uint16_t length) { int len; ck_assert_msg((len = recv(con->sock, data, length, 0)) == length, "wrong len %i\n", len); - ck_assert_msg((len = decrypt_data_fast(con->shared_key, con->recv_nonce, data + 2, length - 2, data)) != -1, + ck_assert_msg((len = decrypt_data_symmetric(con->shared_key, con->recv_nonce, data + 2, length - 2, data)) != -1, "Decrypt failed"); increment_nonce(con->recv_nonce); return len; diff --git a/auto_tests/crypto_test.c b/auto_tests/crypto_test.c index 95cdefcd..0165d6da 100644 --- a/auto_tests/crypto_test.c +++ b/auto_tests/crypto_test.c @@ -126,12 +126,12 @@ START_TEST(test_fast_known) ck_assert_msg(sizeof(test_c) == sizeof(c), "sanity check failed"); ck_assert_msg(sizeof(test_m) == sizeof(m), "sanity check failed"); - clen = encrypt_data_fast(k, nonce, test_m, sizeof(test_m) / sizeof(unsigned char), c); + clen = encrypt_data_symmetric(k, nonce, test_m, sizeof(test_m) / sizeof(unsigned char), c); ck_assert_msg(memcmp(test_c, c, sizeof(c)) == 0, "cyphertext doesn't match test vector"); ck_assert_msg(clen == sizeof(c) / sizeof(unsigned char), "wrong ciphertext length"); - mlen = decrypt_data_fast(k, nonce, test_c, sizeof(test_c) / sizeof(unsigned char), m); + mlen = decrypt_data_symmetric(k, nonce, test_c, sizeof(test_c) / sizeof(unsigned char), m); ck_assert_msg(memcmp(test_m, m, sizeof(m)) == 0, "decrypted text doesn't match test vector"); ck_assert_msg(mlen == sizeof(m) / sizeof(unsigned char), "wrong plaintext length"); @@ -186,8 +186,8 @@ START_TEST(test_endtoend) //Encrypt all four ways c1len = encrypt_data(pk2, sk1, n, m, mlen, c1); c2len = encrypt_data(pk1, sk2, n, m, mlen, c2); - c3len = encrypt_data_fast(k1, n, m, mlen, c3); - c4len = encrypt_data_fast(k2, n, m, mlen, c4); + c3len = encrypt_data_symmetric(k1, n, m, mlen, c3); + c4len = encrypt_data_symmetric(k2, n, m, mlen, c4); ck_assert_msg(c1len == c2len && c1len == c3len && c1len == c4len, "cyphertext lengths differ"); ck_assert_msg(c1len == mlen + (int)crypto_box_MACBYTES, "wrong cyphertext length"); @@ -197,8 +197,8 @@ START_TEST(test_endtoend) //Decrypt all four ways m1len = decrypt_data(pk2, sk1, n, c1, c1len, m1); m2len = decrypt_data(pk1, sk2, n, c1, c1len, m2); - m3len = decrypt_data_fast(k1, n, c1, c1len, m3); - m4len = decrypt_data_fast(k2, n, c1, c1len, m4); + m3len = decrypt_data_symmetric(k1, n, c1, c1len, m3); + m4len = decrypt_data_symmetric(k2, n, c1, c1len, m4); ck_assert_msg(m1len == m2len && m1len == m3len && m1len == m4len, "decrypted text lengths differ"); ck_assert_msg(m1len == mlen, "wrong decrypted text length"); @@ -233,13 +233,13 @@ START_TEST(test_large_data) //Generate key rand_bytes(k, crypto_box_BEFORENMBYTES); - c1len = encrypt_data_fast(k, n, m1, sizeof(m1), c1); - c2len = encrypt_data_fast(k, n, m2, sizeof(m2), c2); + c1len = encrypt_data_symmetric(k, n, m1, sizeof(m1), c1); + c2len = encrypt_data_symmetric(k, n, m2, sizeof(m2), c2); ck_assert_msg(c1len == sizeof(m1) + crypto_box_MACBYTES, "could not encrypt max size"); ck_assert_msg(c2len == -1, "incorrectly succeeded encrypting massive size"); - m1plen = decrypt_data_fast(k, n, c1, c1len, m1prime); + m1plen = decrypt_data_symmetric(k, n, c1, c1len, m1prime); ck_assert_msg(m1plen == sizeof(m1), "decrypted text lengths differ"); ck_assert_msg(memcmp(m1prime, m1, sizeof(m1)) == 0, "decrypted texts differ"); @@ -248,9 +248,9 @@ END_TEST START_TEST(test_large_data_symmetric) { - unsigned char k[crypto_secretbox_KEYBYTES]; + unsigned char k[crypto_box_KEYBYTES]; - unsigned char n[crypto_secretbox_NONCEBYTES]; + unsigned char n[crypto_box_NONCEBYTES]; unsigned char m1[16 * 16 * 16]; unsigned char c1[sizeof(m1) + crypto_box_MACBYTES]; diff --git a/testing/crypto_speed_test.c b/testing/crypto_speed_test.c index 60ff1937..3e81a46b 100644 --- a/testing/crypto_speed_test.c +++ b/testing/crypto_speed_test.c @@ -97,8 +97,8 @@ int main(int argc, char *argv[]) starttime = get_time(); for (trialno = 0; trialno < numtrials; trialno++) { - encrypt_data_fast(k1, n, m, sizeof(m), c); - decrypt_data_fast(k2, n, c, sizeof(c), m); + encrypt_data_symmetric(k1, n, m, sizeof(m), c); + decrypt_data_symmetric(k2, n, c, sizeof(c), m); } endtime = get_time(); diff --git a/toxav/msi.c b/toxav/msi.c index 26e301d3..ee23d03e 100755 --- a/toxav/msi.c +++ b/toxav/msi.c @@ -932,11 +932,11 @@ int handle_recv_start ( MSISession *session, MSIMessage *msg ) session->call->state = call_active; - session->call->key_peer = calloc ( sizeof ( uint8_t ), crypto_secretbox_KEYBYTES ); - memcpy ( session->call->key_peer, msg->cryptokey.header_value, crypto_secretbox_KEYBYTES ); + session->call->key_peer = calloc ( sizeof ( uint8_t ), crypto_box_KEYBYTES ); + memcpy ( session->call->key_peer, msg->cryptokey.header_value, crypto_box_KEYBYTES ); - session->call->nonce_peer = calloc ( sizeof ( uint8_t ), crypto_secretbox_NONCEBYTES ); - memcpy ( session->call->nonce_peer, msg->nonce.header_value, crypto_secretbox_NONCEBYTES ); + session->call->nonce_peer = calloc ( sizeof ( uint8_t ), crypto_box_NONCEBYTES ); + memcpy ( session->call->nonce_peer, msg->nonce.header_value, crypto_box_NONCEBYTES ); flush_peer_type ( session, msg, 0 ); @@ -1030,24 +1030,24 @@ int handle_recv_starting ( MSISession *session, MSIMessage *msg ) } /* Generate local key/nonce to send */ - session->call->key_local = calloc ( sizeof ( uint8_t ), crypto_secretbox_KEYBYTES ); + session->call->key_local = calloc ( sizeof ( uint8_t ), crypto_box_KEYBYTES ); new_symmetric_key ( session->call->key_local ); - session->call->nonce_local = calloc ( sizeof ( uint8_t ), crypto_secretbox_NONCEBYTES ); + session->call->nonce_local = calloc ( sizeof ( uint8_t ), crypto_box_NONCEBYTES ); new_nonce ( session->call->nonce_local ); /* Save peer key/nonce */ - session->call->key_peer = calloc ( sizeof ( uint8_t ), crypto_secretbox_KEYBYTES ); - memcpy ( session->call->key_peer, msg->cryptokey.header_value, crypto_secretbox_KEYBYTES ); + session->call->key_peer = calloc ( sizeof ( uint8_t ), crypto_box_KEYBYTES ); + memcpy ( session->call->key_peer, msg->cryptokey.header_value, crypto_box_KEYBYTES ); - session->call->nonce_peer = calloc ( sizeof ( uint8_t ), crypto_secretbox_NONCEBYTES ); - memcpy ( session->call->nonce_peer, msg->nonce.header_value, crypto_secretbox_NONCEBYTES ); + session->call->nonce_peer = calloc ( sizeof ( uint8_t ), crypto_box_NONCEBYTES ); + memcpy ( session->call->nonce_peer, msg->nonce.header_value, crypto_box_NONCEBYTES ); session->call->state = call_active; MSIMessage *_msg_start = msi_new_message ( TYPE_REQUEST, stringify_request ( start ) ); - msi_msg_set_cryptokey ( _msg_start, session->call->key_local, crypto_secretbox_KEYBYTES ); - msi_msg_set_nonce ( _msg_start, session->call->nonce_local, crypto_secretbox_NONCEBYTES ); + msi_msg_set_cryptokey ( _msg_start, session->call->key_local, crypto_box_KEYBYTES ); + msi_msg_set_nonce ( _msg_start, session->call->nonce_local, crypto_box_NONCEBYTES ); send_message ( session, _msg_start, msg->friend_id ); free_message ( _msg_start ); @@ -1402,14 +1402,14 @@ int msi_answer ( MSISession *session, MSICallType call_type ) /* Now set the local encryption key and pass it with STARTING message */ - session->call->key_local = calloc ( sizeof ( uint8_t ), crypto_secretbox_KEYBYTES ); + session->call->key_local = calloc ( sizeof ( uint8_t ), crypto_box_KEYBYTES ); new_symmetric_key ( session->call->key_local ); - session->call->nonce_local = calloc ( sizeof ( uint8_t ), crypto_secretbox_NONCEBYTES ); + session->call->nonce_local = calloc ( sizeof ( uint8_t ), crypto_box_NONCEBYTES ); new_nonce ( session->call->nonce_local ); - msi_msg_set_cryptokey ( _msg_starting, session->call->key_local, crypto_secretbox_KEYBYTES ); - msi_msg_set_nonce ( _msg_starting, session->call->nonce_local, crypto_secretbox_NONCEBYTES ); + msi_msg_set_cryptokey ( _msg_starting, session->call->key_local, crypto_box_KEYBYTES ); + msi_msg_set_nonce ( _msg_starting, session->call->nonce_local, crypto_box_NONCEBYTES ); send_message ( session, _msg_starting, session->call->peers[session->call->peer_count - 1] ); free_message ( _msg_starting ); diff --git a/toxav/rtp.c b/toxav/rtp.c index b52840c1..7307a168 100755 --- a/toxav/rtp.c +++ b/toxav/rtp.c @@ -168,8 +168,8 @@ inline__ void increase_nonce(uint8_t *nonce, uint16_t target) uint16_t _nonce_counter; uint8_t _reverse_bytes[2]; - _reverse_bytes[0] = nonce[crypto_secretbox_NONCEBYTES - 1]; - _reverse_bytes[1] = nonce[crypto_secretbox_NONCEBYTES - 2]; + _reverse_bytes[0] = nonce[crypto_box_NONCEBYTES - 1]; + _reverse_bytes[1] = nonce[crypto_box_NONCEBYTES - 2]; bytes_to_U16(&_nonce_counter, _reverse_bytes ); @@ -177,8 +177,8 @@ inline__ void increase_nonce(uint8_t *nonce, uint16_t target) if (_nonce_counter > UINT16_MAX - target ) { /* 2 bytes are not long enough */ uint8_t _it = 3; - while ( _it <= crypto_secretbox_NONCEBYTES ) _it += ++nonce[crypto_secretbox_NONCEBYTES - _it] ? - crypto_secretbox_NONCEBYTES : 1; + while ( _it <= crypto_box_NONCEBYTES ) _it += ++nonce[crypto_box_NONCEBYTES - _it] ? + crypto_box_NONCEBYTES : 1; _nonce_counter = _nonce_counter - (UINT16_MAX - target ); /* Assign the rest of it */ } else { /* Increase nonce */ @@ -189,8 +189,8 @@ inline__ void increase_nonce(uint8_t *nonce, uint16_t target) /* Assign the last bytes */ U16_to_bytes( _reverse_bytes, _nonce_counter); - nonce [crypto_secretbox_NONCEBYTES - 1] = _reverse_bytes[0]; - nonce [crypto_secretbox_NONCEBYTES - 2] = _reverse_bytes[1]; + nonce [crypto_box_NONCEBYTES - 1] = _reverse_bytes[0]; + nonce [crypto_box_NONCEBYTES - 2] = _reverse_bytes[1]; } @@ -496,7 +496,7 @@ int rtp_handle_packet ( void *object, IP_Port ip_port, uint8_t *data, uint32_t l RTPSession *_session = object; RTPMessage *_msg; - if ( !_session || length < 13 + crypto_secretbox_MACBYTES) /* 12 is the minimum length for rtp + desc. byte */ + if ( !_session || length < 13 + crypto_box_MACBYTES) /* 12 is the minimum length for rtp + desc. byte */ return -1; uint8_t _plain[MAX_UDP_PACKET_SIZE]; @@ -505,8 +505,8 @@ int rtp_handle_packet ( void *object, IP_Port ip_port, uint8_t *data, uint32_t l bytes_to_U16(&_sequnum, data + 1); /* Clculate the right nonce */ - uint8_t _calculated[crypto_secretbox_NONCEBYTES]; - memcpy(_calculated, _session->decrypt_nonce, crypto_secretbox_NONCEBYTES); + uint8_t _calculated[crypto_box_NONCEBYTES]; + memcpy(_calculated, _session->decrypt_nonce, crypto_box_NONCEBYTES); increase_nonce ( _calculated, _sequnum ); /* Decrypt message */ @@ -536,8 +536,8 @@ int rtp_handle_packet ( void *object, IP_Port ip_port, uint8_t *data, uint32_t l if ( _decrypted_length == -1 ) return -1; /* This is just an error */ /* A new cycle setting. */ - memcpy(_session->nonce_cycle, _session->decrypt_nonce, crypto_secretbox_NONCEBYTES); - memcpy(_session->decrypt_nonce, _calculated, crypto_secretbox_NONCEBYTES); + memcpy(_session->nonce_cycle, _session->decrypt_nonce, crypto_box_NONCEBYTES); + memcpy(_session->decrypt_nonce, _calculated, crypto_box_NONCEBYTES); } } @@ -735,8 +735,8 @@ int rtp_send_msg ( RTPSession *session, Messenger *messenger, const uint8_t *dat _send_data[0] = session->prefix; /* Generate the right nonce */ - uint8_t _calculated[crypto_secretbox_NONCEBYTES]; - memcpy(_calculated, session->encrypt_nonce, crypto_secretbox_NONCEBYTES); + uint8_t _calculated[crypto_box_NONCEBYTES]; + memcpy(_calculated, session->encrypt_nonce, crypto_box_NONCEBYTES); increase_nonce ( _calculated, msg->header->sequnum ); /* Need to skip 2 bytes that are for sequnum */ @@ -760,7 +760,7 @@ int rtp_send_msg ( RTPSession *session, Messenger *messenger, const uint8_t *dat /* Set sequ number */ if ( session->sequnum >= MAX_SEQU_NUM ) { session->sequnum = 0; - memcpy(session->encrypt_nonce, _calculated, crypto_secretbox_NONCEBYTES); + memcpy(session->encrypt_nonce, _calculated, crypto_box_NONCEBYTES); } else { session->sequnum++; } @@ -850,16 +850,16 @@ RTPSession *rtp_init_session ( int payload_type, _retu->decrypt_key = decrypt_key; /* Need to allocate new memory */ - _retu->encrypt_nonce = calloc ( crypto_secretbox_NONCEBYTES, sizeof (uint8_t) ); + _retu->encrypt_nonce = calloc ( crypto_box_NONCEBYTES, sizeof (uint8_t) ); assert(_retu->encrypt_nonce); - _retu->decrypt_nonce = calloc ( crypto_secretbox_NONCEBYTES, sizeof (uint8_t) ); + _retu->decrypt_nonce = calloc ( crypto_box_NONCEBYTES, sizeof (uint8_t) ); assert(_retu->decrypt_nonce); - _retu->nonce_cycle = calloc ( crypto_secretbox_NONCEBYTES, sizeof (uint8_t) ); + _retu->nonce_cycle = calloc ( crypto_box_NONCEBYTES, sizeof (uint8_t) ); assert(_retu->nonce_cycle); - memcpy(_retu->encrypt_nonce, encrypt_nonce, crypto_secretbox_NONCEBYTES); - memcpy(_retu->decrypt_nonce, decrypt_nonce, crypto_secretbox_NONCEBYTES); - memcpy(_retu->nonce_cycle , decrypt_nonce, crypto_secretbox_NONCEBYTES); + memcpy(_retu->encrypt_nonce, encrypt_nonce, crypto_box_NONCEBYTES); + memcpy(_retu->decrypt_nonce, decrypt_nonce, crypto_box_NONCEBYTES); + memcpy(_retu->nonce_cycle , decrypt_nonce, crypto_box_NONCEBYTES); _retu->csrc = calloc(1, sizeof (uint32_t)); assert(_retu->csrc); diff --git a/toxcore/DHT.c b/toxcore/DHT.c index 98b488a2..267d3ef9 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c @@ -925,7 +925,7 @@ end: return 0; } -#define NODES_ENCRYPTED_MESSAGE_LENGTH (crypto_secretbox_NONCEBYTES + sizeof(uint64_t) + sizeof(Node_format) + sizeof(Node_format) + crypto_secretbox_MACBYTES) +#define NODES_ENCRYPTED_MESSAGE_LENGTH (crypto_box_NONCEBYTES + sizeof(uint64_t) + sizeof(Node_format) + sizeof(Node_format) + crypto_box_MACBYTES) /* Send a getnodes request. sendback_node is the node that it will send back the response to (set to NULL to disable this) */ @@ -958,9 +958,9 @@ static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cli nonce, plain_message, sizeof(temp_time) + sizeof(reciever) + sizeof(Node_format), - encrypted_message + crypto_secretbox_NONCEBYTES); + encrypted_message + crypto_box_NONCEBYTES); - if (len_m != NODES_ENCRYPTED_MESSAGE_LENGTH - crypto_secretbox_NONCEBYTES) + if (len_m != NODES_ENCRYPTED_MESSAGE_LENGTH - crypto_box_NONCEBYTES) return -1; uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES]; @@ -973,7 +973,7 @@ static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cli uint8_t shared_key[crypto_box_BEFORENMBYTES]; DHT_get_shared_key_sent(dht, shared_key, public_key); - int len = encrypt_data_fast( shared_key, + int len = encrypt_data_symmetric( shared_key, nonce, plain, CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH, @@ -1019,7 +1019,7 @@ static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_ return -1; memcpy(plain + nodes_length, encrypted_data, NODES_ENCRYPTED_MESSAGE_LENGTH); - int len = encrypt_data_fast( shared_encryption_key, + int len = encrypt_data_symmetric( shared_encryption_key, nonce, plain, nodes_length + NODES_ENCRYPTED_MESSAGE_LENGTH, @@ -1052,7 +1052,7 @@ static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32 uint8_t shared_key[crypto_box_BEFORENMBYTES]; DHT_get_shared_key_recv(dht, shared_key, packet + 1); - int len = decrypt_data_fast( shared_key, + int len = decrypt_data_symmetric( shared_key, packet + 1 + CLIENT_ID_SIZE, packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES, @@ -1075,8 +1075,8 @@ static uint8_t sent_getnode_to_node(DHT *dht, uint8_t *client_id, IP_Port node_i { uint8_t plain_message[NODES_ENCRYPTED_MESSAGE_LENGTH]; - if (decrypt_data_symmetric(dht->secret_symmetric_key, encrypted_data, encrypted_data + crypto_secretbox_NONCEBYTES, - NODES_ENCRYPTED_MESSAGE_LENGTH - crypto_secretbox_NONCEBYTES, + if (decrypt_data_symmetric(dht->secret_symmetric_key, encrypted_data, encrypted_data + crypto_box_NONCEBYTES, + NODES_ENCRYPTED_MESSAGE_LENGTH - crypto_box_NONCEBYTES, plain_message) != sizeof(uint64_t) + sizeof(Node_format) * 2) return 0; @@ -1121,7 +1121,7 @@ static int handle_sendnodes_core(void *object, IP_Port source, uint8_t *packet, uint8_t plain[data_size + NODES_ENCRYPTED_MESSAGE_LENGTH]; uint8_t shared_key[crypto_box_BEFORENMBYTES]; DHT_get_shared_key_sent(dht, shared_key, packet + 1); - int len = decrypt_data_fast( + int len = decrypt_data_symmetric( shared_key, packet + 1 + CLIENT_ID_SIZE, packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, diff --git a/toxcore/DHT.h b/toxcore/DHT.h index 73c44e9b..c4c0db41 100644 --- a/toxcore/DHT.h +++ b/toxcore/DHT.h @@ -177,7 +177,7 @@ typedef struct { uint32_t close_bootstrap_times; /* Note: this key should not be/is not used to transmit any sensitive materials */ - uint8_t secret_symmetric_key[crypto_secretbox_KEYBYTES]; + uint8_t secret_symmetric_key[crypto_box_KEYBYTES]; /* DHT keypair */ uint8_t self_public_key[crypto_box_PUBLICKEYBYTES]; uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; diff --git a/toxcore/Makefile.inc b/toxcore/Makefile.inc index 5e529267..7723aeaf 100644 --- a/toxcore/Makefile.inc +++ b/toxcore/Makefile.inc @@ -9,6 +9,8 @@ libtoxcore_la_SOURCES = ../toxcore/DHT.h \ ../toxcore/DHT.c \ ../toxcore/network.h \ ../toxcore/network.c \ + ../toxcore/crypto_core.h \ + ../toxcore/crypto_core.c \ ../toxcore/Lossless_UDP.h \ ../toxcore/Lossless_UDP.c \ ../toxcore/net_crypto.h \ diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index eb08fb94..0346cbe4 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -2752,75 +2752,6 @@ int messenger_load(Messenger *m, uint8_t *data, uint32_t length) return -1; } -/* return the size of data to pass to messenger_save_encrypted(...) - * - */ -uint32_t messenger_size_encrypted(Messenger *m) -{ - return messenger_size(m) + crypto_secretbox_MACBYTES + crypto_secretbox_NONCEBYTES; -} - -/* Save the messenger, encrypting the data with key of length key_length - * - * return 0 on success. - * return -1 on failure. - */ -int messenger_save_encrypted(Messenger *m, uint8_t *data, uint8_t *key, uint16_t key_length) -{ - uint32_t m_size = messenger_size(m); - uint8_t *plain_messenger = malloc(m_size); - - if (plain_messenger == NULL) - return -1; - - messenger_save(m, plain_messenger); - - /* Hash the key with SHA256 to get a 32byte key. */ - uint8_t hash[crypto_hash_sha256_BYTES]; - crypto_hash_sha256(hash, key, key_length); - random_nonce(data); - encrypt_data_symmetric(hash, data, plain_messenger, m_size, data + crypto_secretbox_NONCEBYTES); - - memset(plain_messenger, 0, m_size); - free(plain_messenger); - memset(hash, 0, crypto_hash_sha256_BYTES); - return 0; -} - -/* Load the messenger from data of size length encrypted with key of key_length. - * - * return 0 on success. - * return -1 on failure. - */ -int messenger_load_encrypted(Messenger *m, uint8_t *data, uint32_t length, uint8_t *key, uint16_t key_length) -{ - if (length <= crypto_secretbox_MACBYTES + crypto_secretbox_NONCEBYTES) - return -1; - - uint8_t *plain_messenger = malloc(length); - - if (plain_messenger == NULL) - return -1; - - /* Hash the key with SHA256 to get a 32byte key. */ - uint8_t hash[crypto_hash_sha256_BYTES]; - crypto_hash_sha256(hash, key, key_length); - int len = decrypt_data_symmetric(hash, data, data + crypto_secretbox_NONCEBYTES, length - crypto_secretbox_NONCEBYTES, - plain_messenger); - int ret; - - if ((uint32_t)len == length - crypto_secretbox_NONCEBYTES - crypto_secretbox_MACBYTES) { - ret = messenger_load(m, plain_messenger, length - crypto_secretbox_NONCEBYTES - crypto_secretbox_MACBYTES); - } else { - ret = -1; - } - - memset(plain_messenger, 0, length); - free(plain_messenger); - memset(hash, 0, crypto_hash_sha256_BYTES); - return ret; -} - /* Return the number of friends in the instance m. * You should use this to determine how much memory to allocate * for copy_friendlist. */ diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index c6d89fac..05c34811 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -736,24 +736,6 @@ void messenger_save(Messenger *m, uint8_t *data); /* Load the messenger from data of size length. */ int messenger_load(Messenger *m, uint8_t *data, uint32_t length); -/* return the size of data to pass to messenger_save_encrypted(...) - */ -uint32_t messenger_size_encrypted(Messenger *m); - -/* Save the messenger, encrypting the data with key of length key_length - * - * return 0 on success. - * return -1 on failure. - */ -int messenger_save_encrypted(Messenger *m, uint8_t *data, uint8_t *key, uint16_t key_length); - -/* Load the messenger from data of size length encrypted with key of key_length. - * - * return 0 on success. - * return -1 on failure. - */ -int messenger_load_encrypted(Messenger *m, uint8_t *data, uint32_t length, uint8_t *key, uint16_t key_length); - /* Return the number of friends in the instance m. * You should use this to determine how much memory to allocate * for copy_friendlist. */ diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c index 4f3411f1..825d762c 100644 --- a/toxcore/TCP_client.c +++ b/toxcore/TCP_client.c @@ -74,7 +74,7 @@ static int generate_handshake(TCP_Client_Connection *TCP_conn, uint8_t *self_pub memcpy(plain + crypto_box_PUBLICKEYBYTES, TCP_conn->sent_nonce, crypto_box_NONCEBYTES); memcpy(TCP_conn->last_packet, self_public_key, crypto_box_PUBLICKEYBYTES); new_nonce(TCP_conn->last_packet + crypto_box_PUBLICKEYBYTES); - int len = encrypt_data_fast(TCP_conn->shared_key, TCP_conn->last_packet + crypto_box_PUBLICKEYBYTES, plain, + int len = encrypt_data_symmetric(TCP_conn->shared_key, TCP_conn->last_packet + crypto_box_PUBLICKEYBYTES, plain, sizeof(plain), TCP_conn->last_packet + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES); if (len != sizeof(plain) + crypto_box_MACBYTES) @@ -93,7 +93,7 @@ static int generate_handshake(TCP_Client_Connection *TCP_conn, uint8_t *self_pub static int handle_handshake(TCP_Client_Connection *TCP_conn, uint8_t *data) { uint8_t plain[crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES]; - int len = decrypt_data_fast(TCP_conn->shared_key, data, data + crypto_box_NONCEBYTES, + int len = decrypt_data_symmetric(TCP_conn->shared_key, data, data + crypto_box_NONCEBYTES, TCP_SERVER_HANDSHAKE_SIZE - crypto_box_NONCEBYTES, plain); if (len != sizeof(plain)) @@ -149,7 +149,7 @@ static int write_packet_TCP_secure_connection(TCP_Client_Connection *con, uint8_ uint16_t c_length = htons(length + crypto_box_MACBYTES); memcpy(packet, &c_length, sizeof(uint16_t)); - int len = encrypt_data_fast(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t)); + int len = encrypt_data_symmetric(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t)); if ((unsigned int)len != (sizeof(packet) - sizeof(uint16_t))) return -1; diff --git a/toxcore/TCP_client.h b/toxcore/TCP_client.h index 7e8be22d..c2daaf9c 100644 --- a/toxcore/TCP_client.h +++ b/toxcore/TCP_client.h @@ -24,7 +24,7 @@ #ifndef TCP_CLIENT_H #define TCP_CLIENT_H -#include "net_crypto.h" +#include "crypto_core.h" #include "TCP_server.h" #define TCP_CONNECTION_TIMEOUT 10 diff --git a/toxcore/TCP_server.c b/toxcore/TCP_server.c index 1c4ffdcb..0ca39c47 100644 --- a/toxcore/TCP_server.c +++ b/toxcore/TCP_server.c @@ -258,7 +258,7 @@ int read_packet_TCP_secure_connection(sock_t sock, uint16_t *next_packet_length, *next_packet_length = 0; - int len = decrypt_data_fast(shared_key, recv_nonce, data_encrypted, len_packet, data); + int len = decrypt_data_symmetric(shared_key, recv_nonce, data_encrypted, len_packet, data); if (len + crypto_box_MACBYTES != len_packet) return -1; @@ -313,7 +313,7 @@ static int write_packet_TCP_secure_connection(TCP_Secure_Connection *con, uint8_ uint16_t c_length = htons(length + crypto_box_MACBYTES); memcpy(packet, &c_length, sizeof(uint16_t)); - int len = encrypt_data_fast(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t)); + int len = encrypt_data_symmetric(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t)); if ((unsigned int)len != (sizeof(packet) - sizeof(uint16_t))) return -1; @@ -356,7 +356,7 @@ static int handle_TCP_handshake(TCP_Secure_Connection *con, uint8_t *data, uint1 uint8_t shared_key[crypto_box_BEFORENMBYTES]; encrypt_precompute(data, self_secret_key, shared_key); uint8_t plain[TCP_HANDSHAKE_PLAIN_SIZE]; - int len = decrypt_data_fast(shared_key, data + crypto_box_PUBLICKEYBYTES, + int len = decrypt_data_symmetric(shared_key, data + crypto_box_PUBLICKEYBYTES, data + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, TCP_HANDSHAKE_PLAIN_SIZE + crypto_box_MACBYTES, plain); if (len != TCP_HANDSHAKE_PLAIN_SIZE) @@ -373,7 +373,7 @@ static int handle_TCP_handshake(TCP_Secure_Connection *con, uint8_t *data, uint1 uint8_t response[TCP_SERVER_HANDSHAKE_SIZE]; new_nonce(response); - len = encrypt_data_fast(shared_key, response, resp_plain, TCP_HANDSHAKE_PLAIN_SIZE, response + crypto_box_NONCEBYTES); + len = encrypt_data_symmetric(shared_key, response, resp_plain, TCP_HANDSHAKE_PLAIN_SIZE, response + crypto_box_NONCEBYTES); if (len != TCP_HANDSHAKE_PLAIN_SIZE + crypto_box_MACBYTES) return -1; diff --git a/toxcore/TCP_server.h b/toxcore/TCP_server.h index 498b1147..e4c45dad 100644 --- a/toxcore/TCP_server.h +++ b/toxcore/TCP_server.h @@ -23,7 +23,7 @@ #ifndef TCP_SERVER_H #define TCP_SERVER_H -#include "net_crypto.h" +#include "crypto_core.h" #include "onion.h" #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__MACH__) diff --git a/toxcore/crypto_core.c b/toxcore/crypto_core.c new file mode 100644 index 00000000..38048076 --- /dev/null +++ b/toxcore/crypto_core.c @@ -0,0 +1,168 @@ +/* net_crypto.c + * + * Functions for the core crypto. + * + * NOTE: This code has to be perfect. We don't mess around with encryption. + * + * Copyright (C) 2013 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "crypto_core.h" + +/* Use this instead of memcmp; not vulnerable to timing attacks. */ +uint8_t crypto_iszero(uint8_t *mem, uint32_t length) +{ + uint8_t check = 0; + uint32_t i; + + for (i = 0; i < length; ++i) { + check |= mem[i]; + } + + return check; // We return zero if mem is made out of zeroes. +} + +/* Precomputes the shared key from their public_key and our secret_key. + * This way we can avoid an expensive elliptic curve scalar multiply for each + * encrypt/decrypt operation. + * enc_key has to be crypto_box_BEFORENMBYTES bytes long. + */ +void encrypt_precompute(uint8_t *public_key, uint8_t *secret_key, uint8_t *enc_key) +{ + crypto_box_beforenm(enc_key, public_key, secret_key); +} + +int encrypt_data_symmetric(uint8_t *secret_key, uint8_t *nonce, uint8_t *plain, uint32_t length, uint8_t *encrypted) +{ + if (length == 0) + return -1; + + uint8_t temp_plain[length + crypto_box_ZEROBYTES]; + uint8_t temp_encrypted[length + crypto_box_MACBYTES + crypto_box_BOXZEROBYTES]; + + memset(temp_plain, 0, crypto_box_ZEROBYTES); + memcpy(temp_plain + crypto_box_ZEROBYTES, plain, length); // Pad the message with 32 0 bytes. + + if (crypto_box_afternm(temp_encrypted, temp_plain, length + crypto_box_ZEROBYTES, nonce, secret_key) != 0) + return -1; + /* Unpad the encrypted message. */ + memcpy(encrypted, temp_encrypted + crypto_box_BOXZEROBYTES, length + crypto_box_MACBYTES); + return length + crypto_box_MACBYTES; +} + +int decrypt_data_symmetric(uint8_t *secret_key, uint8_t *nonce, uint8_t *encrypted, uint32_t length, uint8_t *plain) +{ + if (length <= crypto_box_BOXZEROBYTES) + return -1; + + uint8_t temp_plain[length + crypto_box_ZEROBYTES]; + uint8_t temp_encrypted[length + crypto_box_BOXZEROBYTES]; + + memset(temp_plain, 0, crypto_box_BOXZEROBYTES); + memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length); // Pad the message with 16 0 bytes. + + if (crypto_box_open_afternm(temp_plain, temp_encrypted, length + crypto_box_BOXZEROBYTES, nonce, secret_key) != 0) + return -1; + + memcpy(plain, temp_plain + crypto_box_ZEROBYTES, length - crypto_box_MACBYTES); + return length - crypto_box_MACBYTES; +} + +int encrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, + uint8_t *plain, uint32_t length, uint8_t *encrypted) +{ + uint8_t k[crypto_box_BEFORENMBYTES]; + encrypt_precompute(public_key, secret_key, k); + return encrypt_data_symmetric(k, nonce, plain, length, encrypted); +} + +int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, + uint8_t *encrypted, uint32_t length, uint8_t *plain) +{ + uint8_t k[crypto_box_BEFORENMBYTES]; + encrypt_precompute(public_key, secret_key, k); + return decrypt_data_symmetric(k, nonce, encrypted, length, plain); +} + + +/* Increment the given nonce by 1. */ +void increment_nonce(uint8_t *nonce) +{ + uint32_t i; + + for (i = crypto_box_NONCEBYTES; i != 0; --i) { + ++nonce[i - 1]; + + if (nonce[i - 1] != 0) + break; + } +} +/* increment the given nonce by num */ +void increment_nonce_number(uint8_t *nonce, uint32_t num) +{ + uint32_t num1, num2; + memcpy(&num1, nonce + (crypto_box_NONCEBYTES - sizeof(num1)), sizeof(num1)); + num1 = ntohl(num1); + num2 = num + num1; + + if (num2 < num1) { + uint32_t i; + + for (i = crypto_box_NONCEBYTES - sizeof(num1); i != 0; --i) { + ++nonce[i - 1]; + + if (nonce[i - 1] != 0) + break; + } + } + + num2 = htonl(num2); + memcpy(nonce + (crypto_box_NONCEBYTES - sizeof(num2)), &num2, sizeof(num2)); +} + +/* Fill the given nonce with random bytes. */ +void random_nonce(uint8_t *nonce) +{ + randombytes(nonce, crypto_box_NONCEBYTES); +} + +/* Fill a key crypto_box_KEYBYTES big with random bytes */ +void new_symmetric_key(uint8_t *key) +{ + randombytes(key, crypto_box_KEYBYTES); +} + +static uint8_t base_nonce[crypto_box_NONCEBYTES]; +static uint8_t nonce_set = 0; + +/* Gives a nonce guaranteed to be different from previous ones.*/ +void new_nonce(uint8_t *nonce) +{ + if (nonce_set == 0) { + random_nonce(base_nonce); + nonce_set = 1; + } + + increment_nonce(base_nonce); + memcpy(nonce, base_nonce, crypto_box_NONCEBYTES); +} \ No newline at end of file diff --git a/toxcore/crypto_core.h b/toxcore/crypto_core.h new file mode 100644 index 00000000..6a13b22b --- /dev/null +++ b/toxcore/crypto_core.h @@ -0,0 +1,86 @@ +/* crypto_core.h + * + * Functions for the core crypto. + * + * Copyright (C) 2013 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ +#ifndef CORE_CRYPTO_H +#define CORE_CRYPTO_H + +#include "network.h" + +/* return zero if the buffer contains only zeros. */ +uint8_t crypto_iszero(uint8_t *buffer, uint32_t blen); + +/* Encrypts plain of length length to encrypted of length + 16 using the + * public key(32 bytes) of the receiver and the secret key of the sender and a 24 byte nonce. + * + * return -1 if there was a problem. + * return length of encrypted data if everything was fine. + */ +int encrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, + uint8_t *plain, uint32_t length, uint8_t *encrypted); + + +/* Decrypts encrypted of length length to plain of length length - 16 using the + * public key(32 bytes) of the sender, the secret key of the receiver and a 24 byte nonce. + * + * return -1 if there was a problem (decryption failed). + * return length of plain data if everything was fine. + */ +int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, + uint8_t *encrypted, uint32_t length, uint8_t *plain); + +/* Fast encrypt/decrypt operations. Use if this is not a one-time communication. + encrypt_precompute does the shared-key generation once so it does not have + to be preformed on every encrypt/decrypt. */ +void encrypt_precompute(uint8_t *public_key, uint8_t *secret_key, uint8_t *enc_key); + +/* Encrypts plain of length length to encrypted of length + 16 using a + * secret key crypto_box_KEYBYTES big and a 24 byte nonce. + * + * return -1 if there was a problem. + * return length of encrypted data if everything was fine. + */ +int encrypt_data_symmetric(uint8_t *secret_key, uint8_t *nonce, uint8_t *plain, uint32_t length, uint8_t *encrypted); + +/* Decrypts encrypted of length length to plain of length length - 16 using a + * secret key crypto_box_KEYBYTES big and a 24 byte nonce. + * + * return -1 if there was a problem (decryption failed). + * return length of plain data if everything was fine. + */ +int decrypt_data_symmetric(uint8_t *secret_key, uint8_t *nonce, uint8_t *encrypted, uint32_t length, uint8_t *plain); + +/* Increment the given nonce by 1. */ +void increment_nonce(uint8_t *nonce); + +/* increment the given nonce by num */ +void increment_nonce_number(uint8_t *nonce, uint32_t num); + +/* Fill the given nonce with random bytes. */ +void random_nonce(uint8_t *nonce); + +/* Fill a key crypto_box_KEYBYTES big with random bytes */ +void new_symmetric_key(uint8_t *key); + +/*Gives a nonce guaranteed to be different from previous ones.*/ +void new_nonce(uint8_t *nonce); + +#endif diff --git a/toxcore/friend_requests.h b/toxcore/friend_requests.h index eab359f0..8f25d4c1 100644 --- a/toxcore/friend_requests.h +++ b/toxcore/friend_requests.h @@ -25,8 +25,6 @@ #define FRIEND_REQUESTS_H #include "onion_client.h" -#include "net_crypto.h" - typedef struct { uint32_t nospam; diff --git a/toxcore/group_chats.c b/toxcore/group_chats.c index de39331e..ecc9cea7 100644 --- a/toxcore/group_chats.c +++ b/toxcore/group_chats.c @@ -26,8 +26,9 @@ #include "config.h" #endif -#include "group_chats.h" +#include "DHT.h" #include "assoc.h" +#include "group_chats.h" #include "LAN_discovery.h" #include "util.h" diff --git a/toxcore/group_chats.h b/toxcore/group_chats.h index f218fe42..d9da54a5 100644 --- a/toxcore/group_chats.h +++ b/toxcore/group_chats.h @@ -25,8 +25,6 @@ #ifndef GROUP_CHATS_H #define GROUP_CHATS_H -#include "net_crypto.h" - #define MAX_NICK_BYTES 128 typedef struct { diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index ae3a69a1..d0212d11 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -35,202 +35,6 @@ static uint8_t crypt_connection_id_not_valid(Net_Crypto *c, int crypt_connection return (uint32_t)crypt_connection_id >= c->crypto_connections_length; } -/* Use this instead of memcmp; not vulnerable to timing attacks. */ -uint8_t crypto_iszero(uint8_t *mem, uint32_t length) -{ - uint8_t check = 0; - uint32_t i; - - for (i = 0; i < length; ++i) { - check |= mem[i]; - } - - return check; // We return zero if mem is made out of zeroes. -} - -/* Precomputes the shared key from their public_key and our secret_key. - * This way we can avoid an expensive elliptic curve scalar multiply for each - * encrypt/decrypt operation. - * enc_key has to be crypto_box_BEFORENMBYTES bytes long. - */ -void encrypt_precompute(uint8_t *public_key, uint8_t *secret_key, uint8_t *enc_key) -{ - crypto_box_beforenm(enc_key, public_key, secret_key); -} - -/* Fast encrypt. Depends on enc_key from encrypt_precompute. */ -int encrypt_data_fast(uint8_t *enc_key, uint8_t *nonce, - uint8_t *plain, uint32_t length, uint8_t *encrypted) -{ - if (length + crypto_box_MACBYTES > MAX_DATA_SIZE || length == 0) - return -1; - - uint8_t temp_plain[MAX_DATA_SIZE + crypto_box_ZEROBYTES] = {0}; - uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_BOXZEROBYTES]; - - memcpy(temp_plain + crypto_box_ZEROBYTES, plain, length); // Pad the message with 32 0 bytes. - - crypto_box_afternm(temp_encrypted, temp_plain, length + crypto_box_ZEROBYTES, nonce, enc_key); - - if (crypto_iszero(temp_encrypted, crypto_box_BOXZEROBYTES) != 0) - return -1; - - /* Unpad the encrypted message. */ - memcpy(encrypted, temp_encrypted + crypto_box_BOXZEROBYTES, length + crypto_box_MACBYTES); - return length + crypto_box_MACBYTES; -} - -/* Fast decrypt. Depends on enc_ley from encrypt_precompute. */ -int decrypt_data_fast(uint8_t *enc_key, uint8_t *nonce, - uint8_t *encrypted, uint32_t length, uint8_t *plain) -{ - if (length > MAX_DATA_SIZE || length <= crypto_box_BOXZEROBYTES) - return -1; - - uint8_t temp_plain[MAX_DATA_SIZE + crypto_box_ZEROBYTES]; - uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_BOXZEROBYTES] = {0}; - - memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length); // Pad the message with 16 0 bytes. - - if (crypto_box_open_afternm(temp_plain, temp_encrypted, length + crypto_box_BOXZEROBYTES, - nonce, enc_key) == -1) - return -1; - - /* If decryption is successful the first crypto_box_ZEROBYTES of the message will be zero. - * Apparently memcmp should not be used so we do this instead: - */ - if (crypto_iszero(temp_plain, crypto_box_ZEROBYTES) != 0) - return -1; - - /* Unpad the plain message. */ - memcpy(plain, temp_plain + crypto_box_ZEROBYTES, length - crypto_box_MACBYTES); - return length - crypto_box_MACBYTES; -} - -int encrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, - uint8_t *plain, uint32_t length, uint8_t *encrypted) -{ - uint8_t k[crypto_box_BEFORENMBYTES]; - encrypt_precompute(public_key, secret_key, k); - return encrypt_data_fast(k, nonce, plain, length, encrypted); -} - -int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, - uint8_t *encrypted, uint32_t length, uint8_t *plain) -{ - uint8_t k[crypto_box_BEFORENMBYTES]; - encrypt_precompute(public_key, secret_key, k); - return decrypt_data_fast(k, nonce, encrypted, length, plain); -} - -int encrypt_data_symmetric(uint8_t *secret_key, uint8_t *nonce, uint8_t *plain, uint32_t length, uint8_t *encrypted) -{ - if (length == 0) - return -1; - - uint8_t temp_plain[length + crypto_secretbox_ZEROBYTES]; - uint8_t temp_encrypted[length + crypto_secretbox_MACBYTES + crypto_secretbox_BOXZEROBYTES]; - - memset(temp_plain, 0, crypto_secretbox_ZEROBYTES); - memcpy(temp_plain + crypto_secretbox_ZEROBYTES, plain, length); // Pad the message with 32 0 bytes. - - crypto_secretbox(temp_encrypted, temp_plain, length + crypto_secretbox_ZEROBYTES, nonce, secret_key); - /* Unpad the encrypted message. */ - memcpy(encrypted, temp_encrypted + crypto_secretbox_BOXZEROBYTES, length + crypto_secretbox_MACBYTES); - return length + crypto_secretbox_MACBYTES; -} - -int decrypt_data_symmetric(uint8_t *secret_key, uint8_t *nonce, uint8_t *encrypted, uint32_t length, uint8_t *plain) -{ - if (length <= crypto_secretbox_BOXZEROBYTES) - return -1; - - uint8_t temp_plain[length + crypto_secretbox_ZEROBYTES]; - uint8_t temp_encrypted[length + crypto_secretbox_BOXZEROBYTES]; - - memset(temp_plain, 0, crypto_secretbox_BOXZEROBYTES); - memcpy(temp_encrypted + crypto_secretbox_BOXZEROBYTES, encrypted, length); // Pad the message with 16 0 bytes. - - if (crypto_secretbox_open(temp_plain, temp_encrypted, length + crypto_secretbox_BOXZEROBYTES, nonce, secret_key) == -1) - return -1; - - memcpy(plain, temp_plain + crypto_secretbox_ZEROBYTES, length - crypto_secretbox_MACBYTES); - return length - crypto_secretbox_MACBYTES; -} - -/* Increment the given nonce by 1. */ -void increment_nonce(uint8_t *nonce) -{ - uint32_t i; - - for (i = crypto_box_NONCEBYTES; i != 0; --i) { - ++nonce[i - 1]; - - if (nonce[i - 1] != 0) - break; - } -} -/* increment the given nonce by num */ -void increment_nonce_number(uint8_t *nonce, uint32_t num) -{ - uint32_t num1, num2; - memcpy(&num1, nonce + (crypto_box_NONCEBYTES - sizeof(num1)), sizeof(num1)); - num1 = ntohl(num1); - num2 = num + num1; - - if (num2 < num1) { - uint32_t i; - - for (i = crypto_box_NONCEBYTES - sizeof(num1); i != 0; --i) { - ++nonce[i - 1]; - - if (nonce[i - 1] != 0) - break; - } - } - - num2 = htonl(num2); - memcpy(nonce + (crypto_box_NONCEBYTES - sizeof(num2)), &num2, sizeof(num2)); -} - -#if crypto_box_NONCEBYTES != crypto_secretbox_NONCEBYTES -/*if they no longer equal each other, this function and the previous ones - *must be split into two. - */ -#error random_nonce(): crypto_box_NONCEBYTES must equal crypto_secretbox_NONCEBYTES. -#endif -/* Fill the given nonce with random bytes. */ -void random_nonce(uint8_t *nonce) -{ - randombytes(nonce, crypto_box_NONCEBYTES); -} - -/* Fill a key crypto_secretbox_KEYBYTES big with random bytes */ -void new_symmetric_key(uint8_t *key) -{ - randombytes(key, crypto_secretbox_KEYBYTES); -} - -static uint8_t base_nonce[crypto_box_NONCEBYTES]; -static uint8_t nonce_set = 0; - -#if crypto_box_NONCEBYTES != crypto_secretbox_NONCEBYTES -/*if they no longer equal each other, this function must be split into two.*/ -#error new_nonce(): crypto_box_NONCEBYTES must equal crypto_secretbox_NONCEBYTES. -#endif -/* Gives a nonce guaranteed to be different from previous ones.*/ -void new_nonce(uint8_t *nonce) -{ - if (nonce_set == 0) { - random_nonce(base_nonce); - nonce_set = 1; - } - - increment_nonce(base_nonce); - memcpy(nonce, base_nonce, crypto_box_NONCEBYTES); -} - - /* return 0 if there is no received data in the buffer. * return -1 if the packet was discarded. * return length of received data if successful. @@ -252,7 +56,7 @@ int read_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data) if (temp_data[0] != 3) return -1; - int len = decrypt_data_fast(c->crypto_connections[crypt_connection_id].shared_key, + int len = decrypt_data_symmetric(c->crypto_connections[crypt_connection_id].shared_key, c->crypto_connections[crypt_connection_id].recv_nonce, temp_data + 1, length - 1, data); @@ -290,7 +94,7 @@ int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uin return 0; uint8_t temp_data[MAX_DATA_SIZE]; - int len = encrypt_data_fast(c->crypto_connections[crypt_connection_id].shared_key, + int len = encrypt_data_symmetric(c->crypto_connections[crypt_connection_id].shared_key, c->crypto_connections[crypt_connection_id].sent_nonce, data, length, temp_data + 1); diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index 3c70c4d3..f67ca2bd 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -81,72 +81,6 @@ typedef struct { #include "DHT.h" -/* return zero if the buffer contains only zeros. */ -uint8_t crypto_iszero(uint8_t *buffer, uint32_t blen); - -/* Encrypts plain of length length to encrypted of length + 16 using the - * public key(32 bytes) of the receiver and the secret key of the sender and a 24 byte nonce. - * - * return -1 if there was a problem. - * return length of encrypted data if everything was fine. - */ -int encrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, - uint8_t *plain, uint32_t length, uint8_t *encrypted); - - -/* Decrypts encrypted of length length to plain of length length - 16 using the - * public key(32 bytes) of the sender, the secret key of the receiver and a 24 byte nonce. - * - * return -1 if there was a problem (decryption failed). - * return length of plain data if everything was fine. - */ -int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, - uint8_t *encrypted, uint32_t length, uint8_t *plain); - -/* Fast encrypt/decrypt operations. Use if this is not a one-time communication. - encrypt_precompute does the shared-key generation once so it does not have - to be preformed on every encrypt/decrypt. */ -void encrypt_precompute(uint8_t *public_key, uint8_t *secret_key, uint8_t *enc_key); - -/* Fast encrypt. Depends on enc_key from encrypt_precompute. */ -int encrypt_data_fast(uint8_t *enc_key, uint8_t *nonce, - uint8_t *plain, uint32_t length, uint8_t *encrypted); - -/* Fast decrypt. Depends on enc_ley from encrypt_precompute. */ -int decrypt_data_fast(uint8_t *enc_key, uint8_t *nonce, - uint8_t *encrypted, uint32_t length, uint8_t *plain); - -/* Encrypts plain of length length to encrypted of length + 16 using a - * secret key crypto_secretbox_KEYBYTES big and a 24 byte nonce. - * - * return -1 if there was a problem. - * return length of encrypted data if everything was fine. - */ -int encrypt_data_symmetric(uint8_t *secret_key, uint8_t *nonce, uint8_t *plain, uint32_t length, uint8_t *encrypted); - -/* Decrypts encrypted of length length to plain of length length - 16 using a - * secret key crypto_secretbox_KEYBYTES big and a 24 byte nonce. - * - * return -1 if there was a problem (decryption failed). - * return length of plain data if everything was fine. - */ -int decrypt_data_symmetric(uint8_t *secret_key, uint8_t *nonce, uint8_t *encrypted, uint32_t length, uint8_t *plain); - -/* Increment the given nonce by 1. */ -void increment_nonce(uint8_t *nonce); - -/* increment the given nonce by num */ -void increment_nonce_number(uint8_t *nonce, uint32_t num); - -/* Fill the given nonce with random bytes. */ -void random_nonce(uint8_t *nonce); - -/* Fill a key crypto_secretbox_KEYBYTES big with random bytes */ -void new_symmetric_key(uint8_t *key); - -/*Gives a nonce guaranteed to be different from previous ones.*/ -void new_nonce(uint8_t *nonce); - /* return 0 if there is no received data in the buffer. * return -1 if the packet was discarded. * return length of received data if successful. diff --git a/toxcore/network.h b/toxcore/network.h index 4fca795b..c4fe0a7b 100644 --- a/toxcore/network.h +++ b/toxcore/network.h @@ -102,15 +102,12 @@ typedef int sock_t; #include #else #include -#include #include #include #define crypto_box_MACBYTES (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES) #endif -#ifndef crypto_secretbox_MACBYTES -#define crypto_secretbox_MACBYTES (crypto_secretbox_ZEROBYTES - crypto_secretbox_BOXZEROBYTES) -#endif +#define crypto_box_KEYBYTES (crypto_box_BEFORENMBYTES) #ifndef IPV6_ADD_MEMBERSHIP #ifdef IPV6_JOIN_GROUP diff --git a/toxcore/onion.c b/toxcore/onion.c index ccb729f3..8603de0a 100644 --- a/toxcore/onion.c +++ b/toxcore/onion.c @@ -111,7 +111,7 @@ int send_onion_packet(Networking_Core *net, Onion_Path *path, IP_Port dest, uint memcpy(step2, &path->ip_port3, sizeof(IP_Port)); memcpy(step2 + sizeof(IP_Port), path->public_key3, crypto_box_PUBLICKEYBYTES); - int len = encrypt_data_fast(path->shared_key3, nonce, step1, sizeof(step1), + int len = encrypt_data_symmetric(path->shared_key3, nonce, step1, sizeof(step1), step2 + sizeof(IP_Port) + crypto_box_PUBLICKEYBYTES); if ((uint32_t)len != sizeof(IP_Port) + length + crypto_box_MACBYTES) @@ -120,7 +120,7 @@ int send_onion_packet(Networking_Core *net, Onion_Path *path, IP_Port dest, uint uint8_t step3[sizeof(IP_Port) + SEND_BASE * 2 + length]; memcpy(step3, &path->ip_port2, sizeof(IP_Port)); memcpy(step3 + sizeof(IP_Port), path->public_key2, crypto_box_PUBLICKEYBYTES); - len = encrypt_data_fast(path->shared_key2, nonce, step2, sizeof(step2), + len = encrypt_data_symmetric(path->shared_key2, nonce, step2, sizeof(step2), step3 + sizeof(IP_Port) + crypto_box_PUBLICKEYBYTES); if ((uint32_t)len != sizeof(IP_Port) + SEND_BASE + length + crypto_box_MACBYTES) @@ -131,7 +131,7 @@ int send_onion_packet(Networking_Core *net, Onion_Path *path, IP_Port dest, uint memcpy(packet + 1, nonce, crypto_box_NONCEBYTES); memcpy(packet + 1 + crypto_box_NONCEBYTES, path->public_key1, crypto_box_PUBLICKEYBYTES); - len = encrypt_data_fast(path->shared_key1, nonce, step3, sizeof(step3), + len = encrypt_data_symmetric(path->shared_key1, nonce, step3, sizeof(step3), packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES); if ((uint32_t)len != sizeof(IP_Port) + SEND_BASE * 2 + length + crypto_box_MACBYTES) @@ -175,7 +175,7 @@ static int handle_send_initial(void *object, IP_Port source, uint8_t *packet, ui uint8_t plain[MAX_ONION_SIZE]; uint8_t shared_key[crypto_box_BEFORENMBYTES]; get_shared_key(&onion->shared_keys_1, shared_key, onion->dht->self_secret_key, packet + 1 + crypto_box_NONCEBYTES); - int len = decrypt_data_fast(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, + int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES), plain); if ((uint32_t)len != length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES)) @@ -198,12 +198,12 @@ int onion_send_1(Onion *onion, uint8_t *plain, uint32_t len, IP_Port source, uin uint8_t *ret_part = data + data_len; new_nonce(ret_part); len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, (uint8_t *)&source, sizeof(IP_Port), - ret_part + crypto_secretbox_NONCEBYTES); + ret_part + crypto_box_NONCEBYTES); - if (len != sizeof(IP_Port) + crypto_secretbox_MACBYTES) + if (len != sizeof(IP_Port) + crypto_box_MACBYTES) return 1; - data_len += crypto_secretbox_NONCEBYTES + len; + data_len += crypto_box_NONCEBYTES + len; if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len) return 1; @@ -226,7 +226,7 @@ static int handle_send_1(void *object, IP_Port source, uint8_t *packet, uint32_t uint8_t plain[MAX_ONION_SIZE]; uint8_t shared_key[crypto_box_BEFORENMBYTES]; get_shared_key(&onion->shared_keys_2, shared_key, onion->dht->self_secret_key, packet + 1 + crypto_box_NONCEBYTES); - int len = decrypt_data_fast(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, + int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_1), plain); if ((uint32_t)len != length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_1 + crypto_box_MACBYTES)) @@ -247,12 +247,12 @@ static int handle_send_1(void *object, IP_Port source, uint8_t *packet, uint32_t memcpy(ret_data, &source, sizeof(IP_Port)); memcpy(ret_data + sizeof(IP_Port), packet + (length - RETURN_1), RETURN_1); len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data), - ret_part + crypto_secretbox_NONCEBYTES); + ret_part + crypto_box_NONCEBYTES); - if (len != RETURN_2 - crypto_secretbox_NONCEBYTES) + if (len != RETURN_2 - crypto_box_NONCEBYTES) return 1; - data_len += crypto_secretbox_NONCEBYTES + len; + data_len += crypto_box_NONCEBYTES + len; if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len) return 1; @@ -275,7 +275,7 @@ static int handle_send_2(void *object, IP_Port source, uint8_t *packet, uint32_t uint8_t plain[MAX_ONION_SIZE]; uint8_t shared_key[crypto_box_BEFORENMBYTES]; get_shared_key(&onion->shared_keys_3, shared_key, onion->dht->self_secret_key, packet + 1 + crypto_box_NONCEBYTES); - int len = decrypt_data_fast(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, + int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_2), plain); if ((uint32_t)len != length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_2 + crypto_box_MACBYTES)) @@ -294,9 +294,9 @@ static int handle_send_2(void *object, IP_Port source, uint8_t *packet, uint32_t memcpy(ret_data, &source, sizeof(IP_Port)); memcpy(ret_data + sizeof(IP_Port), packet + (length - RETURN_2), RETURN_2); len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data), - ret_part + crypto_secretbox_NONCEBYTES); + ret_part + crypto_box_NONCEBYTES); - if (len != RETURN_3 - crypto_secretbox_NONCEBYTES) + if (len != RETURN_3 - crypto_box_NONCEBYTES) return 1; data_len += RETURN_3; @@ -321,8 +321,8 @@ static int handle_recv_3(void *object, IP_Port source, uint8_t *packet, uint32_t change_symmetric_key(onion); uint8_t plain[sizeof(IP_Port) + RETURN_2]; - int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_secretbox_NONCEBYTES, - sizeof(IP_Port) + RETURN_2 + crypto_secretbox_MACBYTES, plain); + int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES, + sizeof(IP_Port) + RETURN_2 + crypto_box_MACBYTES, plain); if ((uint32_t)len != sizeof(plain)) return 1; @@ -355,8 +355,8 @@ static int handle_recv_2(void *object, IP_Port source, uint8_t *packet, uint32_t change_symmetric_key(onion); uint8_t plain[sizeof(IP_Port) + RETURN_1]; - int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_secretbox_NONCEBYTES, - sizeof(IP_Port) + RETURN_1 + crypto_secretbox_MACBYTES, plain); + int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES, + sizeof(IP_Port) + RETURN_1 + crypto_box_MACBYTES, plain); if ((uint32_t)len != sizeof(plain)) return 1; @@ -390,8 +390,8 @@ static int handle_recv_1(void *object, IP_Port source, uint8_t *packet, uint32_t IP_Port send_to; - int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_secretbox_NONCEBYTES, - sizeof(IP_Port) + crypto_secretbox_MACBYTES, (uint8_t *) &send_to); + int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES, + sizeof(IP_Port) + crypto_box_MACBYTES, (uint8_t *) &send_to); if ((uint32_t)len != sizeof(IP_Port)) return 1; diff --git a/toxcore/onion.h b/toxcore/onion.h index 4e363724..b15caad9 100644 --- a/toxcore/onion.h +++ b/toxcore/onion.h @@ -28,7 +28,7 @@ typedef struct { DHT *dht; Networking_Core *net; - uint8_t secret_symmetric_key[crypto_secretbox_KEYBYTES]; + uint8_t secret_symmetric_key[crypto_box_KEYBYTES]; uint64_t timestamp; Shared_Keys shared_keys_1; @@ -39,9 +39,9 @@ typedef struct { void *callback_object; } Onion; -#define ONION_RETURN_1 (crypto_secretbox_NONCEBYTES + sizeof(IP_Port) + crypto_secretbox_MACBYTES) -#define ONION_RETURN_2 (crypto_secretbox_NONCEBYTES + sizeof(IP_Port) + crypto_secretbox_MACBYTES + ONION_RETURN_1) -#define ONION_RETURN_3 (crypto_secretbox_NONCEBYTES + sizeof(IP_Port) + crypto_secretbox_MACBYTES + ONION_RETURN_2) +#define ONION_RETURN_1 (crypto_box_NONCEBYTES + sizeof(IP_Port) + crypto_box_MACBYTES) +#define ONION_RETURN_2 (crypto_box_NONCEBYTES + sizeof(IP_Port) + crypto_box_MACBYTES + ONION_RETURN_1) +#define ONION_RETURN_3 (crypto_box_NONCEBYTES + sizeof(IP_Port) + crypto_box_MACBYTES + ONION_RETURN_2) #define ONION_SEND_BASE (crypto_box_PUBLICKEYBYTES + sizeof(IP_Port) + crypto_box_MACBYTES) #define ONION_SEND_3 (crypto_box_NONCEBYTES + ONION_SEND_BASE + ONION_RETURN_2) diff --git a/toxcore/onion_announce.c b/toxcore/onion_announce.c index 7a60a235..28339ee6 100644 --- a/toxcore/onion_announce.c +++ b/toxcore/onion_announce.c @@ -115,11 +115,11 @@ static void generate_ping_id(Onion_Announce *onion_a, uint64_t time, uint8_t *pu uint8_t *ping_id) { time /= PING_ID_TIMEOUT; - uint8_t data[crypto_secretbox_KEYBYTES + sizeof(time) + crypto_box_PUBLICKEYBYTES + sizeof(ret_ip_port)]; - memcpy(data, onion_a->secret_bytes, crypto_secretbox_KEYBYTES); - memcpy(data + crypto_secretbox_KEYBYTES, &time, sizeof(time)); - memcpy(data + crypto_secretbox_KEYBYTES + sizeof(time), public_key, crypto_box_PUBLICKEYBYTES); - memcpy(data + crypto_secretbox_KEYBYTES + sizeof(time) + crypto_box_PUBLICKEYBYTES, &ret_ip_port, sizeof(ret_ip_port)); + uint8_t data[crypto_box_KEYBYTES + sizeof(time) + crypto_box_PUBLICKEYBYTES + sizeof(ret_ip_port)]; + memcpy(data, onion_a->secret_bytes, crypto_box_KEYBYTES); + memcpy(data + crypto_box_KEYBYTES, &time, sizeof(time)); + memcpy(data + crypto_box_KEYBYTES + sizeof(time), public_key, crypto_box_PUBLICKEYBYTES); + memcpy(data + crypto_box_KEYBYTES + sizeof(time) + crypto_box_PUBLICKEYBYTES, &ret_ip_port, sizeof(ret_ip_port)); crypto_hash_sha256(ping_id, data, sizeof(data)); } @@ -221,7 +221,7 @@ static int handle_announce_request(void *object, IP_Port source, uint8_t *packet get_shared_key(&onion_a->shared_keys_recv, shared_key, onion_a->dht->self_secret_key, packet_public_key); uint8_t plain[ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH]; - int len = decrypt_data_fast(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, + int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 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, plain); @@ -278,7 +278,7 @@ static int handle_announce_request(void *object, IP_Port source, uint8_t *packet } uint8_t data[ONION_ANNOUNCE_RESPONSE_MAX_SIZE]; - len = encrypt_data_fast(shared_key, nonce, pl, 1 + ONION_PING_ID_SIZE + nodes_length, + len = encrypt_data_symmetric(shared_key, nonce, pl, 1 + ONION_PING_ID_SIZE + nodes_length, data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES); if (len != 1 + ONION_PING_ID_SIZE + nodes_length + crypto_box_MACBYTES) diff --git a/toxcore/onion_announce.h b/toxcore/onion_announce.h index b7e08363..071dc9ff 100644 --- a/toxcore/onion_announce.h +++ b/toxcore/onion_announce.h @@ -29,7 +29,7 @@ #define ONION_ANNOUNCE_TIMEOUT 300 #define ONION_PING_ID_SIZE crypto_hash_sha256_BYTES -#define ONION_ANNOUNCE_SENDBACK_DATA_LENGTH (crypto_secretbox_NONCEBYTES + sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port) + crypto_secretbox_MACBYTES) +#define ONION_ANNOUNCE_SENDBACK_DATA_LENGTH (crypto_box_NONCEBYTES + sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port) + 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) @@ -52,8 +52,8 @@ typedef struct { DHT *dht; Networking_Core *net; Onion_Announce_Entry entries[ONION_ANNOUNCE_MAX_ENTRIES]; - /* This is crypto_secretbox_KEYBYTES long just so we can use new_symmetric_key() to fill it */ - uint8_t secret_bytes[crypto_secretbox_KEYBYTES]; + /* This is crypto_box_KEYBYTES long just so we can use new_symmetric_key() to fill it */ + uint8_t secret_bytes[crypto_box_KEYBYTES]; Shared_Keys shared_keys_recv; } Onion_Announce; diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index 4a5a37d2..fbb00a2c 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c @@ -116,9 +116,9 @@ static int new_sendback(Onion_Client *onion_c, uint32_t num, uint8_t *public_key memcpy(plain + sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES, &ip_port, sizeof(IP_Port)); int len = encrypt_data_symmetric(onion_c->secret_symmetric_key, sendback, plain, sizeof(plain), - sendback + crypto_secretbox_NONCEBYTES); + sendback + crypto_box_NONCEBYTES); - if ((uint32_t)len + crypto_secretbox_NONCEBYTES != ONION_ANNOUNCE_SENDBACK_DATA_LENGTH) + if ((uint32_t)len + crypto_box_NONCEBYTES != ONION_ANNOUNCE_SENDBACK_DATA_LENGTH) return -1; return 0; @@ -137,8 +137,8 @@ static int new_sendback(Onion_Client *onion_c, uint32_t num, uint8_t *public_key static uint32_t check_sendback(Onion_Client *onion_c, uint8_t *sendback, uint8_t *ret_pubkey, IP_Port *ret_ip_port) { uint8_t plain[sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port)]; - int len = decrypt_data_symmetric(onion_c->secret_symmetric_key, sendback, sendback + crypto_secretbox_NONCEBYTES, - ONION_ANNOUNCE_SENDBACK_DATA_LENGTH - crypto_secretbox_NONCEBYTES, plain); + int len = decrypt_data_symmetric(onion_c->secret_symmetric_key, sendback, sendback + crypto_box_NONCEBYTES, + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH - crypto_box_NONCEBYTES, plain); if ((uint32_t)len != sizeof(plain)) return ~0; diff --git a/toxcore/onion_client.h b/toxcore/onion_client.h index 4045cc0e..8e09b63a 100644 --- a/toxcore/onion_client.h +++ b/toxcore/onion_client.h @@ -113,7 +113,7 @@ typedef struct { Onion_Client_Paths onion_paths; - uint8_t secret_symmetric_key[crypto_secretbox_KEYBYTES]; + uint8_t secret_symmetric_key[crypto_box_KEYBYTES]; uint64_t last_run; uint8_t temp_public_key[crypto_box_PUBLICKEYBYTES]; diff --git a/toxcore/ping.c b/toxcore/ping.c index e43c3b1a..b0928d95 100644 --- a/toxcore/ping.c +++ b/toxcore/ping.c @@ -168,7 +168,7 @@ int send_ping_request(PING *ping, IP_Port ipp, uint8_t *client_id) new_nonce(pk + 1 + CLIENT_ID_SIZE); // Generate new nonce - rc = encrypt_data_fast(shared_key, + rc = encrypt_data_symmetric(shared_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 new_nonce(pk + 1 + CLIENT_ID_SIZE); // Generate new nonce // Encrypt ping_id using recipient privkey - rc = encrypt_data_fast(shared_encryption_key, + rc = encrypt_data_symmetric(shared_encryption_key, pk + 1 + CLIENT_ID_SIZE, (uint8_t *) &ping_id, sizeof(ping_id), pk + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES ); @@ -222,7 +222,7 @@ static int handle_ping_request(void *_dht, IP_Port source, uint8_t *packet, uint // Decrypt ping_id DHT_get_shared_key_recv(dht, shared_key, packet + 1); - rc = decrypt_data_fast(shared_key, + rc = decrypt_data_symmetric(shared_key, packet + 1 + CLIENT_ID_SIZE, packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, sizeof(ping_id) + crypto_box_MACBYTES, @@ -259,7 +259,7 @@ static int handle_ping_response(void *_dht, IP_Port source, uint8_t *packet, uin --ping_index; // Decrypt ping_id - rc = decrypt_data_fast(ping->pings[ping_index].shared_key, + rc = decrypt_data_symmetric(ping->pings[ping_index].shared_key, packet + 1 + CLIENT_ID_SIZE, packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, sizeof(ping_id) + crypto_box_MACBYTES, diff --git a/toxcore/tox.c b/toxcore/tox.c index d78ef091..6bd24e92 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -828,34 +828,4 @@ int tox_load(Tox *tox, uint8_t *data, uint32_t length) { Messenger *m = tox; return messenger_load(m, data, length); -} - -/* return the size of data to pass to messenger_save_encrypted(...) - */ -uint32_t tox_size_encrypted(Tox *tox) -{ - Messenger *m = tox; - return messenger_size_encrypted(m); -} - -/* Save the messenger, encrypting the data with key of length key_length - * - * return 0 on success. - * return -1 on failure. - */ -int tox_save_encrypted(Tox *tox, uint8_t *data, uint8_t *key, uint16_t key_length) -{ - Messenger *m = tox; - return messenger_save_encrypted(m, data, key, key_length); -} - -/* Load the messenger from data of size length encrypted with key of key_length. - * - * return 0 on success. - * return -1 on failure. - */ -int tox_load_encrypted(Tox *tox, uint8_t *data, uint32_t length, uint8_t *key, uint16_t key_length) -{ - Messenger *m = tox; - return messenger_load_encrypted(m, data, length, key, key_length); -} +} \ No newline at end of file diff --git a/toxcore/tox.h b/toxcore/tox.h index fadd1a28..8edf0499 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -702,32 +702,6 @@ void tox_save(Tox *tox, uint8_t *data); */ int tox_load(Tox *tox, uint8_t *data, uint32_t length); -/**/ - -/* return the size of data to pass to messenger_save_encrypted(...) - */ -uint32_t tox_size_encrypted(Tox *tox); - -/* Save the messenger, encrypting the data with key of length key_length - * - * This functions simply calls and then encrypt the output of tox_save(..) - * with crypto_secretbox(...) from NaCl/libsodium with the key - * given to crypto_secretbox(...) being the SHA256 sum of the key - * passed to this function. - * - * return 0 on success. - * return -1 on failure. - */ -int tox_save_encrypted(Tox *tox, uint8_t *data, uint8_t *key, uint16_t key_length); - -/* Load the messenger from data of size length encrypted with key of key_length. - * - * return 0 on success. - * return -1 on failure. - */ -int tox_load_encrypted(Tox *tox, uint8_t *data, uint32_t length, uint8_t *key, uint16_t key_length); - - #ifdef __cplusplus } #endif From 496d4fe203a51769be47f42df50b41db94f4358a Mon Sep 17 00:00:00 2001 From: irungentoo Date: Mon, 21 Apr 2014 16:54:47 -0400 Subject: [PATCH 023/117] Fixed a test. Removed function from Messenger.h --- auto_tests/messenger_test.c | 22 ---------------------- toxcore/Messenger.c | 4 +++- toxcore/Messenger.h | 5 ----- 3 files changed, 3 insertions(+), 28 deletions(-) diff --git a/auto_tests/messenger_test.c b/auto_tests/messenger_test.c index 5e5f7b06..76cbf663 100644 --- a/auto_tests/messenger_test.c +++ b/auto_tests/messenger_test.c @@ -299,27 +299,6 @@ START_TEST(test_messenger_state_saveloadsave) } END_TEST -START_TEST(test_messenger_state_saveload_encrypted) -{ - uint8_t addr[FRIEND_ADDRESS_SIZE]; - getaddress(m, addr); - Messenger *m_temp = new_messenger(TOX_ENABLE_IPV6_DEFAULT); - - size_t size = messenger_size_encrypted(m); - uint8_t buffer[size]; - messenger_save_encrypted(m, buffer, "Gentoo", sizeof("Gentoo")); - - ck_assert_msg(messenger_load_encrypted(m_temp, buffer, size, "Ubuntu", sizeof("Ubuntu")) == -1, - "Bad password didn't make the function fail."); - ck_assert_msg(messenger_load_encrypted(m_temp, buffer, size, "Gentoo", sizeof("Gentoo")) == 0, - "Good password didn't make the function succeed."); - uint8_t addr1[FRIEND_ADDRESS_SIZE]; - getaddress(m_temp, addr1); - ck_assert_msg(memcmp(addr1, addr, FRIEND_ADDRESS_SIZE) == 0, "Didn't load messenger successfully"); - kill_messenger(m_temp); -} -END_TEST - #define DEFTESTCASE(NAME) \ TCase *tc_##NAME = tcase_create(#NAME); \ tcase_add_test(tc_##NAME, test_##NAME); \ @@ -331,7 +310,6 @@ Suite *messenger_suite(void) DEFTESTCASE(dht_state_saveloadsave); DEFTESTCASE(messenger_state_saveloadsave); - DEFTESTCASE(messenger_state_saveload_encrypted); DEFTESTCASE(getself_name); DEFTESTCASE(m_get_userstatus_size); diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 0346cbe4..f7d773dd 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -37,6 +37,8 @@ static void set_friend_status(Messenger *m, int32_t friendnumber, uint8_t status); static int write_cryptpacket_id(Messenger *m, int32_t friendnumber, uint8_t packet_id, uint8_t *data, uint32_t length); +static IP_Port get_friend_ipport(Messenger *m, int32_t friendnumber); + // friend_not_valid determines if the friendnumber passed is valid in the Messenger object static uint8_t friend_not_valid(Messenger *m, int32_t friendnumber) { @@ -875,7 +877,7 @@ static uint8_t groupnumber_not_valid(Messenger *m, int groupnumber) /* returns valid ip port of connected friend on success * returns zeroed out IP_Port on failure */ -IP_Port get_friend_ipport(Messenger *m, int32_t friendnumber) +static IP_Port get_friend_ipport(Messenger *m, int32_t friendnumber) { IP_Port zero; memset(&zero, 0, sizeof(zero)); diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 05c34811..0ce96f44 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -373,11 +373,6 @@ int getname(Messenger *m, int32_t friendnumber, uint8_t *name); int m_get_name_size(Messenger *m, int32_t friendnumber); int m_get_self_name_size(Messenger *m); -/* returns valid ip port of connected friend on success - * returns zeroed out IP_Port on failure - */ -IP_Port get_friend_ipport(Messenger *m, int32_t friendnumber); - /* Set our user status. * You are responsible for freeing status after. * From c46ab5821d0fa8c604de52e15009e2b8da5d9c07 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Mon, 21 Apr 2014 17:09:52 -0400 Subject: [PATCH 024/117] Fixed test. --- auto_tests/crypto_test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/auto_tests/crypto_test.c b/auto_tests/crypto_test.c index 0165d6da..917aa81d 100644 --- a/auto_tests/crypto_test.c +++ b/auto_tests/crypto_test.c @@ -236,8 +236,8 @@ START_TEST(test_large_data) c1len = encrypt_data_symmetric(k, n, m1, sizeof(m1), c1); c2len = encrypt_data_symmetric(k, n, m2, sizeof(m2), c2); - ck_assert_msg(c1len == sizeof(m1) + crypto_box_MACBYTES, "could not encrypt max size"); - ck_assert_msg(c2len == -1, "incorrectly succeeded encrypting massive size"); + ck_assert_msg(c1len == sizeof(m1) + crypto_box_MACBYTES, "could not encrypt"); + ck_assert_msg(c2len == sizeof(m2) + crypto_box_MACBYTES, "could not encrypt"); m1plen = decrypt_data_symmetric(k, n, c1, c1len, m1prime); From 1bfe15ee88844bdbd43052b4026202cf924ad6ca Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 22 Apr 2014 20:28:40 -0400 Subject: [PATCH 025/117] Decided pretty much how the handshake would work. Started writing the code. Astyled some files. --- docs/Tox_middle_level_network_protocol.txt | 24 +++- toxcore/DHT.c | 30 +++-- toxcore/DHT.h | 4 +- toxcore/TCP_client.c | 4 +- toxcore/TCP_server.c | 5 +- toxcore/TCP_server.h | 2 - toxcore/crypto_core.c | 1 + toxcore/net_crypto.c | 148 ++++++++++++++++++++- toxcore/net_crypto.h | 5 + toxcore/network.h | 7 + toxcore/onion.c | 12 +- toxcore/onion_announce.c | 6 +- toxcore/ping.c | 28 ++-- 13 files changed, 226 insertions(+), 50 deletions(-) diff --git a/docs/Tox_middle_level_network_protocol.txt b/docs/Tox_middle_level_network_protocol.txt index ae0fd0f6..be8253cd 100644 --- a/docs/Tox_middle_level_network_protocol.txt +++ b/docs/Tox_middle_level_network_protocol.txt @@ -38,4 +38,26 @@ from evil "friends" framing relays must also be implemented. Detailed implementation details: -Coming soon. +cookie request packet: +[uint8_t 24][Senders DHT Public key (32 bytes)][Random nonce (24 +bytes)][Encrypted message containing: [Senders real public key (32 +bytes)][Recievers real public key (32 bytes)]] +Encrypted message is encrypted with sender DHT private key, recievers DHT public +key and the nonce. + +cookie response packet: +[uint8_t 25][Random nonce (24 bytes)][Encrypted message containing: [Cookie]] +Encrypted message is encrypted with sender DHT private key, recievers DHT public +key and the nonce. + +The Cookie should be basically: +[nonce][encrypted data:[uint64_t time][Senders real public key (32 +bytes)][Recievers real public key (32 bytes)]] + +Handshake packet: +[uint8_t 26][Cookie][nonce][Encrypted message containing: [random 24 bytes base +nonce][session public key of the peer (32 bytes)]] + +The handshake packet is encrypted using the real private key of the sender, the +real private key of the reciever and the nonce. + diff --git a/toxcore/DHT.c b/toxcore/DHT.c index 267d3ef9..5b43cdb0 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c @@ -163,7 +163,7 @@ void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, uint8_t *secr } } -/* Copy shared_key to decrypt DHT packet from client_id into shared_key +/* Copy shared_key to encrypt/decrypt DHT packet from client_id into shared_key * for packets that we recieve. */ void DHT_get_shared_key_recv(DHT *dht, uint8_t *shared_key, uint8_t *client_id) @@ -171,7 +171,7 @@ void DHT_get_shared_key_recv(DHT *dht, uint8_t *shared_key, uint8_t *client_id) return get_shared_key(&dht->shared_keys_recv, shared_key, dht->self_secret_key, client_id); } -/* Copy shared_key to decrypt DHT packet from client_id into shared_key +/* Copy shared_key to encrypt/decrypt DHT packet from client_id into shared_key * for packets that we send. */ void DHT_get_shared_key_sent(DHT *dht, uint8_t *shared_key, uint8_t *client_id) @@ -974,10 +974,10 @@ static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cli uint8_t shared_key[crypto_box_BEFORENMBYTES]; DHT_get_shared_key_sent(dht, shared_key, public_key); int len = encrypt_data_symmetric( shared_key, - nonce, - plain, - CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH, - encrypt ); + nonce, + plain, + CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH, + encrypt ); if (len != CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES) return -1; @@ -1020,10 +1020,10 @@ static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_ memcpy(plain + nodes_length, encrypted_data, NODES_ENCRYPTED_MESSAGE_LENGTH); int len = encrypt_data_symmetric( shared_encryption_key, - nonce, - plain, - nodes_length + NODES_ENCRYPTED_MESSAGE_LENGTH, - encrypt ); + nonce, + plain, + nodes_length + NODES_ENCRYPTED_MESSAGE_LENGTH, + encrypt ); if ((unsigned int)len != nodes_length + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES) return -1; @@ -1053,10 +1053,10 @@ static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32 DHT_get_shared_key_recv(dht, shared_key, packet + 1); int len = decrypt_data_symmetric( shared_key, - packet + 1 + CLIENT_ID_SIZE, - packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, - CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES, - plain ); + packet + 1 + CLIENT_ID_SIZE, + packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, + CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES, + plain ); if (len != CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH) return 1; @@ -2283,6 +2283,7 @@ DHT *new_DHT(Net_Crypto *c) DHT_addfriend(dht, random_key_bytes); } + c->dht = dht; return dht; } @@ -2317,6 +2318,7 @@ void kill_DHT(DHT *dht) networking_registerhandler(dht->net, NET_PACKET_SEND_NODES_IPV6, NULL, NULL); cryptopacket_registerhandler(dht->c, CRYPTO_PACKET_NAT_PING, NULL, NULL); cryptopacket_registerhandler(dht->c, CRYPTO_PACKET_HARDENING, NULL, NULL); + dht->c->dht = 0; kill_ping(dht->ping); free(dht->friends_list); free(dht); diff --git a/toxcore/DHT.h b/toxcore/DHT.h index c4c0db41..0c59dc81 100644 --- a/toxcore/DHT.h +++ b/toxcore/DHT.h @@ -204,12 +204,12 @@ typedef struct { */ void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, uint8_t *secret_key, uint8_t *client_id); -/* Copy shared_key to decrypt DHT packet from client_id into shared_key +/* Copy shared_key to encrypt/decrypt DHT packet from client_id into shared_key * for packets that we recieve. */ void DHT_get_shared_key_recv(DHT *dht, uint8_t *shared_key, uint8_t *client_id); -/* Copy shared_key to decrypt DHT packet from client_id into shared_key +/* Copy shared_key to encrypt/decrypt DHT packet from client_id into shared_key * for packets that we send. */ void DHT_get_shared_key_sent(DHT *dht, uint8_t *shared_key, uint8_t *client_id); diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c index 825d762c..3745e14d 100644 --- a/toxcore/TCP_client.c +++ b/toxcore/TCP_client.c @@ -75,7 +75,7 @@ static int generate_handshake(TCP_Client_Connection *TCP_conn, uint8_t *self_pub memcpy(TCP_conn->last_packet, self_public_key, crypto_box_PUBLICKEYBYTES); new_nonce(TCP_conn->last_packet + crypto_box_PUBLICKEYBYTES); int len = encrypt_data_symmetric(TCP_conn->shared_key, TCP_conn->last_packet + crypto_box_PUBLICKEYBYTES, plain, - sizeof(plain), TCP_conn->last_packet + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES); + sizeof(plain), TCP_conn->last_packet + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES); if (len != sizeof(plain) + crypto_box_MACBYTES) return -1; @@ -94,7 +94,7 @@ static int handle_handshake(TCP_Client_Connection *TCP_conn, uint8_t *data) { uint8_t plain[crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES]; int len = decrypt_data_symmetric(TCP_conn->shared_key, data, data + crypto_box_NONCEBYTES, - TCP_SERVER_HANDSHAKE_SIZE - crypto_box_NONCEBYTES, plain); + TCP_SERVER_HANDSHAKE_SIZE - crypto_box_NONCEBYTES, plain); if (len != sizeof(plain)) return -1; diff --git a/toxcore/TCP_server.c b/toxcore/TCP_server.c index 0ca39c47..fa49274a 100644 --- a/toxcore/TCP_server.c +++ b/toxcore/TCP_server.c @@ -357,7 +357,7 @@ static int handle_TCP_handshake(TCP_Secure_Connection *con, uint8_t *data, uint1 encrypt_precompute(data, self_secret_key, shared_key); uint8_t plain[TCP_HANDSHAKE_PLAIN_SIZE]; int len = decrypt_data_symmetric(shared_key, data + crypto_box_PUBLICKEYBYTES, - data + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, TCP_HANDSHAKE_PLAIN_SIZE + crypto_box_MACBYTES, plain); + data + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, TCP_HANDSHAKE_PLAIN_SIZE + crypto_box_MACBYTES, plain); if (len != TCP_HANDSHAKE_PLAIN_SIZE) return -1; @@ -373,7 +373,8 @@ static int handle_TCP_handshake(TCP_Secure_Connection *con, uint8_t *data, uint1 uint8_t response[TCP_SERVER_HANDSHAKE_SIZE]; new_nonce(response); - len = encrypt_data_symmetric(shared_key, response, resp_plain, TCP_HANDSHAKE_PLAIN_SIZE, response + crypto_box_NONCEBYTES); + len = encrypt_data_symmetric(shared_key, response, resp_plain, TCP_HANDSHAKE_PLAIN_SIZE, + response + crypto_box_NONCEBYTES); if (len != TCP_HANDSHAKE_PLAIN_SIZE + crypto_box_MACBYTES) return -1; diff --git a/toxcore/TCP_server.h b/toxcore/TCP_server.h index e4c45dad..26cfa493 100644 --- a/toxcore/TCP_server.h +++ b/toxcore/TCP_server.h @@ -54,8 +54,6 @@ #define ARRAY_ENTRY_SIZE 6 -#define TCP_ONION_FAMILY (AF_INET6 + 1) - /* frequency to ping connected nodes and timeout in seconds */ #define TCP_PING_FREQUENCY 30 #define TCP_PING_TIMEOUT 20 diff --git a/toxcore/crypto_core.c b/toxcore/crypto_core.c index 38048076..22612442 100644 --- a/toxcore/crypto_core.c +++ b/toxcore/crypto_core.c @@ -65,6 +65,7 @@ int encrypt_data_symmetric(uint8_t *secret_key, uint8_t *nonce, uint8_t *plain, if (crypto_box_afternm(temp_encrypted, temp_plain, length + crypto_box_ZEROBYTES, nonce, secret_key) != 0) return -1; + /* Unpad the encrypted message. */ memcpy(encrypted, temp_encrypted + crypto_box_BOXZEROBYTES, length + crypto_box_MACBYTES); return length + crypto_box_MACBYTES; diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index d0212d11..3eb9ca4c 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -34,6 +34,145 @@ static uint8_t crypt_connection_id_not_valid(Net_Crypto *c, int crypt_connection { return (uint32_t)crypt_connection_id >= c->crypto_connections_length; } +#define COOKIE_REQUEST_PLAIN_LENGTH (crypto_box_PUBLICKEYBYTES * 2) +#define COOKIE_REQUEST_LENGTH (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + COOKIE_REQUEST_PLAIN_LENGTH + crypto_box_MACBYTES) + +/* Create a cookie request packet and put it in packet. + * + * packet must be of size COOKIE_REQUEST_LENGTH or bigger. + * + * return -1 on failure. + * return COOKIE_REQUEST_LENGTH on success. + */ +static int create_cookie_request(Net_Crypto *c, uint8_t *packet, uint8_t *dht_public_key, uint8_t *real_public_key) +{ + if (!c->dht) + return -1; + + uint8_t plain[COOKIE_REQUEST_PLAIN_LENGTH]; + + memcpy(plain, c->self_public_key, crypto_box_PUBLICKEYBYTES); + memcpy(plain + crypto_box_PUBLICKEYBYTES, real_public_key, crypto_box_PUBLICKEYBYTES); + + uint8_t shared_key[crypto_box_BEFORENMBYTES]; + DHT_get_shared_key_sent(c->dht, shared_key, dht_public_key); + uint8_t nonce[crypto_box_NONCEBYTES]; + new_nonce(nonce); + packet[0] = NET_PACKET_COOKIE_REQUEST; + memcpy(packet + 1, c->dht->self_public_key, crypto_box_PUBLICKEYBYTES); + memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES); + int len = encrypt_data_symmetric(shared_key, nonce, plain, sizeof(plain), + packet + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES); + + if (len != COOKIE_REQUEST_PLAIN_LENGTH + crypto_box_MACBYTES) + return -1; + + return (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + len); +} + +/* cookie timeout in seconds */ +#define COOKIE_TIMEOUT 10 +#define COOKIE_CONTENTS_LENGTH (sizeof(uint64_t) + COOKIE_REQUEST_PLAIN_LENGTH) +#define COOKIE_LENGTH (crypto_box_NONCEBYTES + COOKIE_CONTENTS_LENGTH + crypto_box_MACBYTES) + +/* Create cookie of length COOKIE_LENGTH from bytes of length COOKIE_REQUEST_PLAIN_LENGTH using encryption_key + * + * return -1 on failure. + * return 0 on success. + */ +static int create_cookie(uint8_t *cookie, uint8_t *bytes, uint8_t *encryption_key) +{ + uint8_t contents[COOKIE_CONTENTS_LENGTH]; + uint64_t temp_time = unix_time(); + memcpy(contents, &temp_time, sizeof(temp_time)); + memcpy(contents + sizeof(temp_time), bytes, COOKIE_REQUEST_PLAIN_LENGTH); + new_nonce(cookie); + int len = encrypt_data_symmetric(encryption_key, cookie, contents, sizeof(contents), cookie + crypto_box_NONCEBYTES); + + if (len != COOKIE_LENGTH - crypto_box_NONCEBYTES) + return -1; + + return 0; +} + +#define COOKIE_RESPONSE_LENGTH (1 + crypto_box_NONCEBYTES + COOKIE_LENGTH + crypto_box_MACBYTES) + +/* Open cookie of length COOKIE_LENGTH from bytes of length COOKIE_REQUEST_PLAIN_LENGTH using encryption_key + * + * return -1 on failure. + * return 0 on success. + */ +static int open_cookie(uint8_t *bytes, uint8_t *cookie, uint8_t *encryption_key) +{ + uint8_t contents[COOKIE_CONTENTS_LENGTH]; + int len = decrypt_data_symmetric(encryption_key, cookie, cookie + crypto_box_NONCEBYTES, + COOKIE_LENGTH - crypto_box_NONCEBYTES, contents); + + if (len != sizeof(contents)) + return -1; + + uint64_t cookie_time; + memcpy(&cookie_time, contents, sizeof(cookie_time)); + uint64_t temp_time = unix_time(); + + if (cookie_time + COOKIE_TIMEOUT < temp_time || temp_time < cookie_time) + return -1; + + memcpy(bytes, contents + sizeof(cookie_time), COOKIE_REQUEST_PLAIN_LENGTH); + return 0; +} + + +/* Create a cookie request packet and put it in packet. + * request_plain must be COOKIE_REQUEST_PLAIN_LENGTH bytes. + * packet must be of size COOKIE_RESPONSE_LENGTH or bigger. + * + * return -1 on failure. + * return COOKIE_RESPONSE_LENGTH on success. + */ +static int create_cookie_response(Net_Crypto *c, uint8_t *packet, uint8_t *request_plain, uint8_t *shared_key) +{ + uint8_t cookie[COOKIE_LENGTH]; + + if (create_cookie(cookie, request_plain, c->secret_symmetric_key) != 0) + return -1; + + packet[0] = NET_PACKET_COOKIE_RESPONSE; + new_nonce(packet + 1); + int len = encrypt_data_symmetric(shared_key, packet + 1, cookie, sizeof(cookie), packet + 1 + crypto_box_NONCEBYTES); + + if (len != COOKIE_RESPONSE_LENGTH - (1 + crypto_box_NONCEBYTES)) + return -1; + + return COOKIE_RESPONSE_LENGTH; +} + +/* Handle the cookie request packet of length length. + * Put what was in the request in request_plain (must be of size COOKIE_REQUEST_PLAIN_LENGTH) + * Put the key used to decrypt the request into shared_key (of size crypto_box_BEFORENMBYTES) for use in the response. + * + * return -1 on failure. + * return 0 on success. + */ +static int handle_cookie_request(Net_Crypto *c, uint8_t *request_plain, uint8_t *shared_key, uint8_t *packet, + uint16_t length) +{ + if (!c->dht) + return -1; + + if (length != COOKIE_REQUEST_LENGTH) + return -1; + + DHT_get_shared_key_sent(c->dht, shared_key, packet + 1); + int len = decrypt_data_symmetric(shared_key, packet + 1 + crypto_box_PUBLICKEYBYTES, + packet + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, COOKIE_REQUEST_PLAIN_LENGTH + crypto_box_MACBYTES, + request_plain); + + if (len != COOKIE_REQUEST_PLAIN_LENGTH) + return -1; + + return 0; +} /* return 0 if there is no received data in the buffer. * return -1 if the packet was discarded. @@ -57,8 +196,8 @@ int read_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data) return -1; int len = decrypt_data_symmetric(c->crypto_connections[crypt_connection_id].shared_key, - c->crypto_connections[crypt_connection_id].recv_nonce, - temp_data + 1, length - 1, data); + c->crypto_connections[crypt_connection_id].recv_nonce, + temp_data + 1, length - 1, data); if (len != -1) { increment_nonce(c->crypto_connections[crypt_connection_id].recv_nonce); @@ -95,8 +234,8 @@ int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uin uint8_t temp_data[MAX_DATA_SIZE]; int len = encrypt_data_symmetric(c->crypto_connections[crypt_connection_id].shared_key, - c->crypto_connections[crypt_connection_id].sent_nonce, - data, length, temp_data + 1); + c->crypto_connections[crypt_connection_id].sent_nonce, + data, length, temp_data + 1); if (len == -1) return 0; @@ -655,6 +794,7 @@ Net_Crypto *new_net_crypto(Networking_Core *net) } new_keys(temp); + new_symmetric_key(temp->secret_symmetric_key); return temp; } diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index f67ca2bd..bbb9ee23 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -25,6 +25,7 @@ #define NET_CRYPTO_H #include "Lossless_UDP.h" +#include "DHT.h" #define CRYPTO_PACKET_FRIEND_REQ 32 /* Friend request crypto packet ID. */ #define CRYPTO_PACKET_HARDENING 48 /* Hardening crypto packet ID. */ @@ -67,6 +68,7 @@ typedef struct { typedef struct { Lossless_UDP *lossless_udp; + DHT *dht; Crypto_Connection *crypto_connections; @@ -76,6 +78,9 @@ typedef struct { uint8_t self_public_key[crypto_box_PUBLICKEYBYTES]; uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; + /* The secret key used for cookies */ + uint8_t secret_symmetric_key[crypto_secretbox_KEYBYTES]; + Cryptopacket_Handles cryptopackethandlers[256]; } Net_Crypto; diff --git a/toxcore/network.h b/toxcore/network.h index c4fe0a7b..0e79954f 100644 --- a/toxcore/network.h +++ b/toxcore/network.h @@ -126,6 +126,8 @@ typedef int sock_t; #define NET_PACKET_HANDSHAKE 16 /* Handshake packet ID. */ #define NET_PACKET_SYNC 17 /* SYNC packet ID. */ #define NET_PACKET_DATA 18 /* Data packet ID. */ +#define NET_PACKET_COOKIE_REQUEST 24 /* Cookie request packet */ +#define NET_PACKET_COOKIE_RESPONSE 25 /* Cookie response packet */ #define NET_PACKET_CRYPTO 32 /* Encrypted data packet ID. */ #define NET_PACKET_LAN_DISCOVERY 33 /* LAN discovery packet ID. */ #define NET_PACKET_GROUP_CHATS 48 /* Group chats packet ID. */ @@ -158,6 +160,11 @@ typedef int sock_t; #define TOX_PORTRANGE_TO 33545 #define TOX_PORT_DEFAULT TOX_PORTRANGE_FROM +/* TCP related */ +#define TCP_ONION_FAMILY (AF_INET6 + 1) +#define TCP_INET (AF_INET6 + 2) +#define TCP_INET6 (AF_INET6 + 3) + typedef union __attribute__ ((__packed__)) { uint8_t uint8[4]; diff --git a/toxcore/onion.c b/toxcore/onion.c index 8603de0a..c2ca21f8 100644 --- a/toxcore/onion.c +++ b/toxcore/onion.c @@ -112,7 +112,7 @@ int send_onion_packet(Networking_Core *net, Onion_Path *path, IP_Port dest, uint memcpy(step2 + sizeof(IP_Port), path->public_key3, crypto_box_PUBLICKEYBYTES); int len = encrypt_data_symmetric(path->shared_key3, nonce, step1, sizeof(step1), - step2 + sizeof(IP_Port) + crypto_box_PUBLICKEYBYTES); + step2 + sizeof(IP_Port) + crypto_box_PUBLICKEYBYTES); if ((uint32_t)len != sizeof(IP_Port) + length + crypto_box_MACBYTES) return -1; @@ -121,7 +121,7 @@ int send_onion_packet(Networking_Core *net, Onion_Path *path, IP_Port dest, uint memcpy(step3, &path->ip_port2, sizeof(IP_Port)); memcpy(step3 + sizeof(IP_Port), path->public_key2, crypto_box_PUBLICKEYBYTES); len = encrypt_data_symmetric(path->shared_key2, nonce, step2, sizeof(step2), - step3 + sizeof(IP_Port) + crypto_box_PUBLICKEYBYTES); + step3 + sizeof(IP_Port) + crypto_box_PUBLICKEYBYTES); if ((uint32_t)len != sizeof(IP_Port) + SEND_BASE + length + crypto_box_MACBYTES) return -1; @@ -132,7 +132,7 @@ int send_onion_packet(Networking_Core *net, Onion_Path *path, IP_Port dest, uint memcpy(packet + 1 + crypto_box_NONCEBYTES, path->public_key1, crypto_box_PUBLICKEYBYTES); len = encrypt_data_symmetric(path->shared_key1, nonce, step3, sizeof(step3), - packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES); + packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES); if ((uint32_t)len != sizeof(IP_Port) + SEND_BASE * 2 + length + crypto_box_MACBYTES) return -1; @@ -176,7 +176,7 @@ static int handle_send_initial(void *object, IP_Port source, uint8_t *packet, ui uint8_t shared_key[crypto_box_BEFORENMBYTES]; get_shared_key(&onion->shared_keys_1, shared_key, onion->dht->self_secret_key, packet + 1 + crypto_box_NONCEBYTES); int len = decrypt_data_symmetric(shared_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), plain); if ((uint32_t)len != length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES)) return 1; @@ -227,7 +227,7 @@ static int handle_send_1(void *object, IP_Port source, uint8_t *packet, uint32_t uint8_t shared_key[crypto_box_BEFORENMBYTES]; get_shared_key(&onion->shared_keys_2, shared_key, onion->dht->self_secret_key, packet + 1 + crypto_box_NONCEBYTES); int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, - length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_1), plain); + length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_1), plain); if ((uint32_t)len != length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_1 + crypto_box_MACBYTES)) return 1; @@ -276,7 +276,7 @@ static int handle_send_2(void *object, IP_Port source, uint8_t *packet, uint32_t uint8_t shared_key[crypto_box_BEFORENMBYTES]; get_shared_key(&onion->shared_keys_3, shared_key, onion->dht->self_secret_key, packet + 1 + crypto_box_NONCEBYTES); int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, - length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_2), plain); + length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_2), plain); if ((uint32_t)len != length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_2 + crypto_box_MACBYTES)) return 1; diff --git a/toxcore/onion_announce.c b/toxcore/onion_announce.c index 28339ee6..5bab931a 100644 --- a/toxcore/onion_announce.c +++ b/toxcore/onion_announce.c @@ -222,8 +222,8 @@ static int handle_announce_request(void *object, IP_Port source, uint8_t *packet uint8_t plain[ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH]; int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 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, 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; @@ -279,7 +279,7 @@ static int handle_announce_request(void *object, IP_Port source, uint8_t *packet uint8_t data[ONION_ANNOUNCE_RESPONSE_MAX_SIZE]; len = encrypt_data_symmetric(shared_key, nonce, pl, 1 + ONION_PING_ID_SIZE + nodes_length, - data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES); + data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES); if (len != 1 + ONION_PING_ID_SIZE + nodes_length + crypto_box_MACBYTES) return 1; diff --git a/toxcore/ping.c b/toxcore/ping.c index b0928d95..35aab86f 100644 --- a/toxcore/ping.c +++ b/toxcore/ping.c @@ -169,9 +169,9 @@ int send_ping_request(PING *ping, IP_Port ipp, uint8_t *client_id) rc = encrypt_data_symmetric(shared_key, - pk + 1 + CLIENT_ID_SIZE, - (uint8_t *) &ping_id, sizeof(ping_id), - pk + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES); + pk + 1 + CLIENT_ID_SIZE, + (uint8_t *) &ping_id, sizeof(ping_id), + pk + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES); if (rc != sizeof(ping_id) + crypto_box_MACBYTES) return 1; @@ -194,9 +194,9 @@ static int send_ping_response(PING *ping, IP_Port ipp, uint8_t *client_id, uint6 // Encrypt ping_id using recipient privkey rc = encrypt_data_symmetric(shared_encryption_key, - pk + 1 + CLIENT_ID_SIZE, - (uint8_t *) &ping_id, sizeof(ping_id), - pk + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES ); + pk + 1 + CLIENT_ID_SIZE, + (uint8_t *) &ping_id, sizeof(ping_id), + pk + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES ); if (rc != sizeof(ping_id) + crypto_box_MACBYTES) return 1; @@ -223,10 +223,10 @@ static int handle_ping_request(void *_dht, IP_Port source, uint8_t *packet, uint // Decrypt ping_id DHT_get_shared_key_recv(dht, shared_key, packet + 1); rc = decrypt_data_symmetric(shared_key, - packet + 1 + CLIENT_ID_SIZE, - packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, - sizeof(ping_id) + crypto_box_MACBYTES, - (uint8_t *) &ping_id ); + packet + 1 + CLIENT_ID_SIZE, + packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, + sizeof(ping_id) + crypto_box_MACBYTES, + (uint8_t *) &ping_id ); if (rc != sizeof(ping_id)) return 1; @@ -260,10 +260,10 @@ static int handle_ping_response(void *_dht, IP_Port source, uint8_t *packet, uin --ping_index; // Decrypt ping_id rc = decrypt_data_symmetric(ping->pings[ping_index].shared_key, - packet + 1 + CLIENT_ID_SIZE, - packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, - sizeof(ping_id) + crypto_box_MACBYTES, - (uint8_t *) &ping_id); + packet + 1 + CLIENT_ID_SIZE, + packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, + sizeof(ping_id) + crypto_box_MACBYTES, + (uint8_t *) &ping_id); if (rc != sizeof(ping_id)) return 1; From 384750af8cf9e339989ded452181e1238ed6e307 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Wed, 23 Apr 2014 11:35:40 -0400 Subject: [PATCH 026/117] Major cleanups. Fixed circular dependency between DHT and net_crypto: DHT no longer depends on net_crypto. Moved the crypto request packets functions to crypto core and DHT. Cleaned up/added some defines that can be used to get the true maximum length of things like the friends request message. MAX_DATA_SIZE has been replaced in most places by more appropriate defines. --- toxcore/DHT.c | 67 ++++++++++++++++----- toxcore/DHT.h | 15 ++++- toxcore/Messenger.c | 29 +++++---- toxcore/Messenger.h | 6 +- toxcore/crypto_core.c | 71 +++++++++++++++++++++- toxcore/crypto_core.h | 31 ++++++++++ toxcore/friend_requests.c | 8 +-- toxcore/friend_requests.h | 5 +- toxcore/group_chats.c | 12 ++-- toxcore/net_crypto.c | 120 ++------------------------------------ toxcore/net_crypto.h | 41 +------------ toxcore/onion.c | 40 +++++++------ toxcore/onion.h | 7 +++ toxcore/onion_announce.c | 7 ++- toxcore/onion_announce.h | 5 ++ toxcore/onion_client.c | 47 +++++++-------- toxcore/onion_client.h | 7 ++- 17 files changed, 275 insertions(+), 243 deletions(-) diff --git a/toxcore/DHT.c b/toxcore/DHT.c index 5b43cdb0..8b553581 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c @@ -1685,7 +1685,7 @@ int friend_ips(DHT *dht, IP_Port *ip_portlist, uint8_t *friend_id) static int send_NATping(DHT *dht, uint8_t *public_key, uint64_t ping_id, uint8_t type) { uint8_t data[sizeof(uint64_t) + 1]; - uint8_t packet[MAX_DATA_SIZE]; + uint8_t packet[MAX_CRYPTO_REQUEST_SIZE]; int num = 0; @@ -1896,7 +1896,7 @@ static int send_hardening_req(DHT *dht, Node_format *sendto, uint8_t type, uint8 if (length > HARDREQ_DATA_SIZE - 1) return -1; - uint8_t packet[MAX_DATA_SIZE]; + uint8_t packet[MAX_CRYPTO_REQUEST_SIZE]; uint8_t data[HARDREQ_DATA_SIZE] = {0}; data[0] = type; memcpy(data + 1, contents, length); @@ -1925,7 +1925,7 @@ static int send_hardening_getnode_res(DHT *dht, Node_format *sendto, uint8_t *qu if (!ip_isset(&sendto->ip_port.ip)) return -1; - uint8_t packet[MAX_DATA_SIZE]; + uint8_t packet[MAX_CRYPTO_REQUEST_SIZE]; uint8_t data[1 + CLIENT_ID_SIZE + nodes_data_length]; data[0] = CHECK_TYPE_GETNODE_RES; memcpy(data + 1, queried_client_id, CLIENT_ID_SIZE); @@ -2242,12 +2242,54 @@ void do_hardening(DHT *dht) /*----------------------------------------------------------------------------------*/ -DHT *new_DHT(Net_Crypto *c) +void cryptopacket_registerhandler(DHT *dht, uint8_t byte, cryptopacket_handler_callback cb, void *object) +{ + dht->cryptopackethandlers[byte].function = cb; + dht->cryptopackethandlers[byte].object = object; +} + +static int cryptopacket_handle(void *object, IP_Port source, uint8_t *packet, uint32_t length) +{ + DHT *dht = object; + + if (packet[0] == NET_PACKET_CRYPTO) { + if (length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + crypto_box_MACBYTES || + length > MAX_CRYPTO_REQUEST_SIZE + crypto_box_MACBYTES) + return 1; + + 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_CRYPTO_REQUEST_SIZE]; + uint8_t number; + 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; + + if (!dht->cryptopackethandlers[number].function) return 1; + + return dht->cryptopackethandlers[number].function(dht->cryptopackethandlers[number].object, source, public_key, + data, len); + + } else { /* If request is not for us, try routing it. */ + int retval = route_packet(dht, packet + 1, packet, length); + + if ((unsigned int)retval == length) + return 0; + } + } + + return 1; +} + +/*----------------------------------------------------------------------------------*/ + +DHT *new_DHT(Networking_Core *net) { /* init time */ unix_time_update(); - if (c == NULL) + if (net == NULL) return NULL; DHT *dht = calloc(1, sizeof(DHT)); @@ -2255,8 +2297,7 @@ DHT *new_DHT(Net_Crypto *c) if (dht == NULL) return NULL; - dht->c = c; - dht->net = c->lossless_udp->net; + dht->net = net; dht->ping = new_ping(dht); if (dht->ping == NULL) { @@ -2266,9 +2307,9 @@ DHT *new_DHT(Net_Crypto *c) networking_registerhandler(dht->net, NET_PACKET_GET_NODES, &handle_getnodes, 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); + networking_registerhandler(dht->net, NET_PACKET_CRYPTO, &cryptopacket_handle, dht); + cryptopacket_registerhandler(dht, CRYPTO_PACKET_NAT_PING, &handle_NATping, dht); + cryptopacket_registerhandler(dht, CRYPTO_PACKET_HARDENING, &handle_hardening, dht); new_symmetric_key(dht->secret_symmetric_key); crypto_box_keypair(dht->self_public_key, dht->self_secret_key); @@ -2283,7 +2324,6 @@ DHT *new_DHT(Net_Crypto *c) DHT_addfriend(dht, random_key_bytes); } - c->dht = dht; return dht; } @@ -2316,9 +2356,8 @@ void kill_DHT(DHT *dht) networking_registerhandler(dht->net, NET_PACKET_GET_NODES, NULL, NULL); networking_registerhandler(dht->net, NET_PACKET_SEND_NODES, NULL, NULL); networking_registerhandler(dht->net, NET_PACKET_SEND_NODES_IPV6, NULL, NULL); - cryptopacket_registerhandler(dht->c, CRYPTO_PACKET_NAT_PING, NULL, NULL); - cryptopacket_registerhandler(dht->c, CRYPTO_PACKET_HARDENING, NULL, NULL); - dht->c->dht = 0; + cryptopacket_registerhandler(dht, CRYPTO_PACKET_NAT_PING, NULL, NULL); + cryptopacket_registerhandler(dht, CRYPTO_PACKET_HARDENING, NULL, NULL); kill_ping(dht->ping); free(dht->friends_list); free(dht); diff --git a/toxcore/DHT.h b/toxcore/DHT.h index 0c59dc81..c08b498c 100644 --- a/toxcore/DHT.h +++ b/toxcore/DHT.h @@ -24,7 +24,7 @@ #ifndef DHT_H #define DHT_H -#include "net_crypto.h" +#include "crypto_core.h" /* Size of the client_id in bytes. */ #define CLIENT_ID_SIZE crypto_box_PUBLICKEYBYTES @@ -168,8 +168,15 @@ typedef struct { /*----------------------------------------------------------------------------------*/ +typedef int (*cryptopacket_handler_callback)(void *object, IP_Port ip_port, uint8_t *source_pubkey, uint8_t *data, + uint32_t len); + +typedef struct { + cryptopacket_handler_callback function; + void *object; +} Cryptopacket_Handles; + typedef struct { - Net_Crypto *c; Networking_Core *net; Client_data close_clientlist[LCLIENT_LIST]; @@ -193,6 +200,8 @@ typedef struct { struct Assoc *assoc; #endif uint64_t last_run; + + Cryptopacket_Handles cryptopackethandlers[256]; } DHT; /*----------------------------------------------------------------------------------*/ @@ -354,7 +363,7 @@ void DHT_save(DHT *dht, uint8_t *data); int DHT_load(DHT *dht, uint8_t *data, uint32_t length); /* Initialize DHT. */ -DHT *new_DHT(Net_Crypto *c); +DHT *new_DHT(Networking_Core *net); void kill_DHT(DHT *dht); diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index f7d773dd..308cf14e 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -214,9 +214,7 @@ void getaddress(Messenger *m, uint8_t *address) */ int32_t m_addfriend(Messenger *m, uint8_t *address, uint8_t *data, uint16_t length) { - if (length >= (MAX_DATA_SIZE - crypto_box_PUBLICKEYBYTES - - crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES - + crypto_box_ZEROBYTES)) + if (length > MAX_FRIEND_REQUEST_DATA_SIZE) return FAERR_TOOLONG; uint8_t client_id[crypto_box_PUBLICKEYBYTES]; @@ -1757,26 +1755,26 @@ Messenger *new_messenger(uint8_t ipv6enabled) return NULL; } - m->net_crypto = new_net_crypto(m->net); + m->dht = new_DHT(m->net); - if (m->net_crypto == NULL) { + if (m->dht == NULL) { kill_networking(m->net); free(m); return NULL; } - m->dht = new_DHT(m->net_crypto); + m->net_crypto = new_net_crypto(m->dht); - if (m->dht == NULL) { - kill_net_crypto(m->net_crypto); + if (m->net_crypto == NULL) { kill_networking(m->net); + kill_DHT(m->dht); free(m); return NULL; } m->onion = new_onion(m->dht); m->onion_a = new_onion_announce(m->dht); - m->onion_c = new_onion_client(m->dht); + m->onion_c = new_onion_client(m->net_crypto); if (!(m->onion && m->onion_a && m->onion_c)) { kill_onion(m->onion); @@ -2409,10 +2407,12 @@ int wait_cleanup_messenger(Messenger *m, uint8_t *data) #define MESSENGER_STATE_TYPE_STATUSMESSAGE 5 #define MESSENGER_STATE_TYPE_STATUS 6 +#define SAVED_FRIEND_REQUEST_SIZE 1024 + struct SAVED_FRIEND { uint8_t status; uint8_t client_id[CLIENT_ID_SIZE]; - uint8_t info[MAX_DATA_SIZE]; // the data that is sent during the friend requests we do. + uint8_t info[SAVED_FRIEND_REQUEST_SIZE]; // the data that is sent during the friend requests we do. uint16_t info_size; // Length of the info. uint8_t name[MAX_NAME_LENGTH]; uint16_t name_length; @@ -2428,7 +2428,7 @@ struct SAVED_FRIEND { struct SAVED_FRIEND_OLD { uint8_t status; uint8_t client_id[CLIENT_ID_SIZE]; - uint8_t info[MAX_DATA_SIZE]; + uint8_t info[1024]; uint16_t info_size; uint8_t name[MAX_NAME_LENGTH]; uint16_t name_length; @@ -2456,7 +2456,12 @@ static uint32_t friends_list_save(Messenger *m, uint8_t *data) memcpy(temp.client_id, m->friendlist[i].client_id, CLIENT_ID_SIZE); if (temp.status < 3) { - memcpy(temp.info, m->friendlist[i].info, m->friendlist[i].info_size); + if (m->friendlist[i].info_size > SAVED_FRIEND_REQUEST_SIZE) { + memcpy(temp.info, m->friendlist[i].info, SAVED_FRIEND_REQUEST_SIZE); + } else { + memcpy(temp.info, m->friendlist[i].info, m->friendlist[i].info_size); + } + temp.info_size = htons(m->friendlist[i].info_size); temp.friendrequest_nospam = m->friendlist[i].friendrequest_nospam; } else { diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 0ce96f44..3d42e911 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -44,9 +44,9 @@ #define PACKET_ID_STATUSMESSAGE 49 #define PACKET_ID_USERSTATUS 50 #define PACKET_ID_TYPING 51 -#define PACKET_ID_RECEIPT 65 +#define PACKET_ID_RECEIPT 63 #define PACKET_ID_MESSAGE 64 -#define PACKET_ID_ACTION 63 +#define PACKET_ID_ACTION 65 #define PACKET_ID_MSI 69 #define PACKET_ID_FILE_SENDREQUEST 80 #define PACKET_ID_FILE_CONTROL 81 @@ -134,7 +134,7 @@ typedef struct { uint64_t friendrequest_lastsent; // Time at which the last friend request was sent. uint32_t friendrequest_timeout; // The timeout between successful friendrequest sending attempts. uint8_t status; // 0 if no friend, 1 if added, 2 if friend request sent, 3 if confirmed friend, 4 if online. - uint8_t info[MAX_DATA_SIZE]; // the data that is sent during the friend requests we do. + uint8_t info[MAX_FRIEND_REQUEST_DATA_SIZE]; // the data that is sent during the friend requests we do. uint8_t name[MAX_NAME_LENGTH]; uint16_t name_length; uint8_t name_sent; // 0 if we didn't send our name to this friend 1 if we have. diff --git a/toxcore/crypto_core.c b/toxcore/crypto_core.c index 22612442..59053bc4 100644 --- a/toxcore/crypto_core.c +++ b/toxcore/crypto_core.c @@ -166,4 +166,73 @@ void new_nonce(uint8_t *nonce) increment_nonce(base_nonce); memcpy(nonce, base_nonce, crypto_box_NONCEBYTES); -} \ No newline at end of file +} + +/* Create a request to peer. + * send_public_key and send_secret_key are the pub/secret keys of the sender. + * recv_public_key is public key of reciever. + * packet must be an array of MAX_CRYPTO_REQUEST_SIZE big. + * Data represents the data we send with the request with length being the length of the data. + * request_id is the id of the request (32 = friend request, 254 = ping request). + * + * return -1 on failure. + * return the length of the created packet on success. + */ +int create_request(uint8_t *send_public_key, uint8_t *send_secret_key, uint8_t *packet, uint8_t *recv_public_key, + uint8_t *data, uint32_t length, uint8_t request_id) +{ + if (MAX_CRYPTO_REQUEST_SIZE < length + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + + crypto_box_MACBYTES) + return -1; + + uint8_t nonce[crypto_box_NONCEBYTES]; + uint8_t temp[MAX_CRYPTO_REQUEST_SIZE]; + memcpy(temp + 1, data, length); + temp[0] = request_id; + new_nonce(nonce); + int len = encrypt_data(recv_public_key, send_secret_key, nonce, temp, length + 1, + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + packet); + + if (len == -1) + return -1; + + packet[0] = NET_PACKET_CRYPTO; + memcpy(packet + 1, recv_public_key, crypto_box_PUBLICKEYBYTES); + memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, send_public_key, crypto_box_PUBLICKEYBYTES); + memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES * 2, nonce, crypto_box_NONCEBYTES); + + return len + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES; +} + +/* Puts the senders public key in the request in public_key, the data from the request + * in data if a friend or ping request was sent to us and returns the length of the data. + * packet is the request packet and length is its length. + * + * return -1 if not valid request. + */ +int handle_request(uint8_t *self_public_key, uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data, + uint8_t *request_id, uint8_t *packet, uint16_t length) +{ + if (length > crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + crypto_box_MACBYTES && + length <= MAX_CRYPTO_REQUEST_SIZE) { + if (memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) { + memcpy(public_key, packet + 1 + crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); + uint8_t nonce[crypto_box_NONCEBYTES]; + uint8_t temp[MAX_CRYPTO_REQUEST_SIZE]; + memcpy(nonce, packet + 1 + crypto_box_PUBLICKEYBYTES * 2, crypto_box_NONCEBYTES); + int len1 = decrypt_data(public_key, self_secret_key, nonce, + packet + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES, + length - (crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1), temp); + + if (len1 == -1 || len1 == 0) + return -1; + + request_id[0] = temp[0]; + --len1; + memcpy(data, temp + 1, len1); + return len1; + } + } + + return -1; +} diff --git a/toxcore/crypto_core.h b/toxcore/crypto_core.h index 6a13b22b..a862635e 100644 --- a/toxcore/crypto_core.h +++ b/toxcore/crypto_core.h @@ -25,6 +25,7 @@ #include "network.h" + /* return zero if the buffer contains only zeros. */ uint8_t crypto_iszero(uint8_t *buffer, uint32_t blen); @@ -83,4 +84,34 @@ void new_symmetric_key(uint8_t *key); /*Gives a nonce guaranteed to be different from previous ones.*/ void new_nonce(uint8_t *nonce); +#define MAX_CRYPTO_REQUEST_SIZE 1024 + +#define CRYPTO_PACKET_FRIEND_REQ 32 /* Friend request crypto packet ID. */ +#define CRYPTO_PACKET_HARDENING 48 /* Hardening crypto packet ID. */ +#define CRYPTO_PACKET_NAT_PING 254 /* NAT ping crypto packet ID. */ +#define CRYPTO_PACKET_GROUP_CHAT_GET_NODES 48 /* Group chat get Nodes packet */ +#define CRYPTO_PACKET_GROUP_CHAT_SEND_NODES 49 /* Group chat send Nodes packet */ +#define CRYPTO_PACKET_GROUP_CHAT_BROADCAST 50 /* Group chat broadcast packet */ + +/* Create a request to peer. + * send_public_key and send_secret_key are the pub/secret keys of the sender. + * recv_public_key is public key of reciever. + * packet must be an array of MAX_CRYPTO_REQUEST_SIZE big. + * Data represents the data we send with the request with length being the length of the data. + * request_id is the id of the request (32 = friend request, 254 = ping request). + * + * return -1 on failure. + * return the length of the created packet on success. + */ +int create_request(uint8_t *send_public_key, uint8_t *send_secret_key, uint8_t *packet, uint8_t *recv_public_key, + uint8_t *data, uint32_t length, uint8_t request_id); + +/* puts the senders public key in the request in public_key, the data from the request + in data if a friend or ping request was sent to us and returns the length of the data. + packet is the request packet and length is its length + return -1 if not valid request. */ +int handle_request(uint8_t *self_public_key, uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data, + uint8_t *request_id, uint8_t *packet, uint16_t length); + + #endif diff --git a/toxcore/friend_requests.c b/toxcore/friend_requests.c index c5cfa4b4..eb2a791c 100644 --- a/toxcore/friend_requests.c +++ b/toxcore/friend_requests.c @@ -37,10 +37,10 @@ */ 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) + if (1 + sizeof(nospam_num) + length > ONION_CLIENT_MAX_DATA_SIZE || length == 0) return -1; - uint8_t temp[MAX_DATA_SIZE]; + uint8_t temp[1 + sizeof(nospam_num) + length]; temp[0] = CRYPTO_PACKET_FRIEND_REQ; memcpy(temp + 1, &nospam_num, sizeof(nospam_num)); memcpy(temp + 1 + sizeof(nospam_num), data, length); @@ -50,7 +50,7 @@ int send_friendrequest(Onion_Client *onion_c, uint8_t *public_key, uint32_t nosp if (friend_num == -1) return -1; - int num = send_onion_data(onion_c, friend_num, temp, 1 + sizeof(nospam_num) + length); + int num = send_onion_data(onion_c, friend_num, temp, sizeof(temp)); if (num <= 0) return -1; @@ -137,7 +137,7 @@ static int friendreq_handlepacket(void *object, uint8_t *source_pubkey, uint8_t { Friend_Requests *fr = object; - if (length <= 1 + sizeof(fr->nospam) || length > MAX_DATA_SIZE) + if (length <= 1 + sizeof(fr->nospam) || length > ONION_CLIENT_MAX_DATA_SIZE) return 1; ++packet; diff --git a/toxcore/friend_requests.h b/toxcore/friend_requests.h index 8f25d4c1..429ffbad 100644 --- a/toxcore/friend_requests.h +++ b/toxcore/friend_requests.h @@ -26,6 +26,8 @@ #include "onion_client.h" +#define MAX_FRIEND_REQUEST_DATA_SIZE (ONION_CLIENT_MAX_DATA_SIZE - (1 + sizeof(uint32_t))) + typedef struct { uint32_t nospam; void (*handle_friendrequest)(void *, uint8_t *, uint8_t *, uint16_t, void *); @@ -46,7 +48,8 @@ typedef struct { } Friend_Requests; /* Try to send a friendrequest to peer with public_key. - * data is the data in the request and length is the length. + * data is the data in the request and length is the length. + * Maximum length of data is MAX_FRIEND_REQUEST_DATA_SIZE. */ 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. */ diff --git a/toxcore/group_chats.c b/toxcore/group_chats.c index ecc9cea7..fbe76d16 100644 --- a/toxcore/group_chats.c +++ b/toxcore/group_chats.c @@ -32,7 +32,7 @@ #include "LAN_discovery.h" #include "util.h" -#define GROUPCHAT_MAXDATA_LENGTH (MAX_DATA_SIZE - (1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES)) +#define GROUPCHAT_MAXDATA_LENGTH (MAX_CRYPTO_REQUEST_SIZE - (1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES)) #define GROUPCHAT_MAXPLAINDATA_LENGTH (GROUPCHAT_MAXDATA_LENGTH - crypto_box_MACBYTES) #define GROUP_MAX_SENDNODES (GROUP_CLOSE_CONNECTIONS * 2) @@ -181,7 +181,7 @@ static int send_groupchatpacket(Group_Chat *chat, IP_Port ip_port, uint8_t *publ if (id_equal(chat->self_public_key, public_key)) return -1; - uint8_t packet[MAX_DATA_SIZE]; + uint8_t packet[MAX_CRYPTO_REQUEST_SIZE]; int len = create_request(chat->self_public_key, chat->self_secret_key, packet, public_key, data, length, request_id); packet[0] = NET_PACKET_GROUP_CHATS; @@ -587,10 +587,10 @@ static int handle_data(Group_Chat *chat, uint8_t *data, uint32_t len) static uint8_t send_data(Group_Chat *chat, uint8_t *data, uint32_t len, uint8_t message_id) { - if (len + GROUP_DATA_MIN_SIZE > MAX_DATA_SIZE) /*NOTE: not the real maximum len.*/ + if (len + GROUP_DATA_MIN_SIZE > MAX_CRYPTO_REQUEST_SIZE) /*NOTE: not the real maximum len.*/ return 1; - uint8_t packet[MAX_DATA_SIZE]; + uint8_t packet[MAX_CRYPTO_REQUEST_SIZE]; ++chat->message_number; if (chat->message_number == 0) @@ -616,11 +616,11 @@ static uint8_t send_data(Group_Chat *chat, uint8_t *data, uint32_t len, uint8_t int handle_groupchatpacket(Group_Chat *chat, IP_Port source, uint8_t *packet, uint32_t length) { - if (length > MAX_DATA_SIZE) + if (length > MAX_CRYPTO_REQUEST_SIZE) return 1; uint8_t public_key[crypto_box_PUBLICKEYBYTES]; - uint8_t data[MAX_DATA_SIZE]; + uint8_t data[MAX_CRYPTO_REQUEST_SIZE]; uint8_t number; int len = handle_request(chat->self_public_key, chat->self_secret_key, public_key, data, &number, packet, length); diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 3eb9ca4c..2136e09f 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -249,113 +249,6 @@ int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uin return 1; } -/* Create a request to peer. - * send_public_key and send_secret_key are the pub/secret keys of the sender. - * recv_public_key is public key of reciever. - * packet must be an array of MAX_DATA_SIZE big. - * Data represents the data we send with the request with length being the length of the data. - * request_id is the id of the request (32 = friend request, 254 = ping request). - * - * return -1 on failure. - * return the length of the created packet on success. - */ -int create_request(uint8_t *send_public_key, uint8_t *send_secret_key, uint8_t *packet, uint8_t *recv_public_key, - uint8_t *data, uint32_t length, uint8_t request_id) -{ - if (MAX_DATA_SIZE < length + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + crypto_box_MACBYTES) - return -1; - - uint8_t nonce[crypto_box_NONCEBYTES]; - uint8_t temp[MAX_DATA_SIZE]; - memcpy(temp + 1, data, length); - temp[0] = request_id; - new_nonce(nonce); - int len = encrypt_data(recv_public_key, send_secret_key, nonce, temp, length + 1, - 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + packet); - - if (len == -1) - return -1; - - packet[0] = NET_PACKET_CRYPTO; - memcpy(packet + 1, recv_public_key, crypto_box_PUBLICKEYBYTES); - memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, send_public_key, crypto_box_PUBLICKEYBYTES); - memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES * 2, nonce, crypto_box_NONCEBYTES); - - return len + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES; -} - -/* Puts the senders public key in the request in public_key, the data from the request - * in data if a friend or ping request was sent to us and returns the length of the data. - * packet is the request packet and length is its length. - * - * return -1 if not valid request. - */ -int handle_request(uint8_t *self_public_key, uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data, - uint8_t *request_id, uint8_t *packet, uint16_t length) -{ - if (length > crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + crypto_box_MACBYTES && - length <= MAX_DATA_SIZE) { - if (memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) { - memcpy(public_key, packet + 1 + crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); - uint8_t nonce[crypto_box_NONCEBYTES]; - uint8_t temp[MAX_DATA_SIZE]; - memcpy(nonce, packet + 1 + crypto_box_PUBLICKEYBYTES * 2, crypto_box_NONCEBYTES); - int len1 = decrypt_data(public_key, self_secret_key, nonce, - packet + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES, - length - (crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1), temp); - - if (len1 == -1 || len1 == 0) - return -1; - - request_id[0] = temp[0]; - --len1; - memcpy(data, temp + 1, len1); - return len1; - } - } - - return -1; -} - -void cryptopacket_registerhandler(Net_Crypto *c, uint8_t byte, cryptopacket_handler_callback cb, void *object) -{ - c->cryptopackethandlers[byte].function = cb; - c->cryptopackethandlers[byte].object = object; -} - -static int cryptopacket_handle(void *object, IP_Port source, uint8_t *packet, uint32_t length) -{ - DHT *dht = object; - - if (packet[0] == NET_PACKET_CRYPTO) { - if (length <= crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + crypto_box_MACBYTES || - length > MAX_DATA_SIZE + crypto_box_MACBYTES) - return 1; - - 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->self_public_key, dht->self_secret_key, public_key, data, &number, packet, length); - - if (len == -1 || len == 0) - return 1; - - if (!dht->c->cryptopackethandlers[number].function) return 1; - - return dht->c->cryptopackethandlers[number].function(dht->c->cryptopackethandlers[number].object, source, public_key, - data, len); - - } else { /* If request is not for us, try routing it. */ - int retval = route_packet(dht, packet + 1, packet, length); - - if ((unsigned int)retval == length) - return 0; - } - } - - return 1; -} /* Send a crypto handshake packet containing an encrypted secret nonce and session public key * to peer with connection_id and public_key. @@ -774,11 +667,11 @@ static void receive_crypto(Net_Crypto *c) /* Run this to (re)initialize net_crypto. * Sets all the global connection variables to their default values. */ -Net_Crypto *new_net_crypto(Networking_Core *net) +Net_Crypto *new_net_crypto(DHT *dht) { unix_time_update(); - if (net == NULL) + if (dht == NULL) return NULL; Net_Crypto *temp = calloc(1, sizeof(Net_Crypto)); @@ -786,7 +679,8 @@ Net_Crypto *new_net_crypto(Networking_Core *net) if (temp == NULL) return NULL; - temp->lossless_udp = new_lossless_udp(net); + temp->dht = dht; + temp->lossless_udp = new_lossless_udp(dht->net); if (temp->lossless_udp == NULL) { free(temp); @@ -798,12 +692,6 @@ Net_Crypto *new_net_crypto(Networking_Core *net) return temp; } -void init_cryptopackets(void *dht) -{ - DHT *s_dht = dht; - networking_registerhandler(s_dht->c->lossless_udp->net, NET_PACKET_CRYPTO, &cryptopacket_handle, s_dht); -} - static void kill_timedout(Net_Crypto *c) { uint32_t i; diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index bbb9ee23..ef56b304 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -27,12 +27,6 @@ #include "Lossless_UDP.h" #include "DHT.h" -#define CRYPTO_PACKET_FRIEND_REQ 32 /* Friend request crypto packet ID. */ -#define CRYPTO_PACKET_HARDENING 48 /* Hardening crypto packet ID. */ -#define CRYPTO_PACKET_NAT_PING 254 /* NAT ping crypto packet ID. */ -#define CRYPTO_PACKET_GROUP_CHAT_GET_NODES 48 /* Group chat get Nodes packet */ -#define CRYPTO_PACKET_GROUP_CHAT_SEND_NODES 49 /* Group chat send Nodes packet */ -#define CRYPTO_PACKET_GROUP_CHAT_BROADCAST 50 /* Group chat broadcast packet */ #define CRYPTO_HANDSHAKE_TIMEOUT (CONNECTION_TIMEOUT * 2) #define CRYPTO_CONN_NO_CONNECTION 0 @@ -58,13 +52,6 @@ typedef struct { } Crypto_Connection; -typedef int (*cryptopacket_handler_callback)(void *object, IP_Port ip_port, uint8_t *source_pubkey, uint8_t *data, - uint32_t len); - -typedef struct { - cryptopacket_handler_callback function; - void *object; -} Cryptopacket_Handles; typedef struct { Lossless_UDP *lossless_udp; @@ -79,9 +66,7 @@ typedef struct { uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; /* The secret key used for cookies */ - uint8_t secret_symmetric_key[crypto_secretbox_KEYBYTES]; - - Cryptopacket_Handles cryptopackethandlers[256]; + uint8_t secret_symmetric_key[crypto_box_KEYBYTES]; } Net_Crypto; #include "DHT.h" @@ -102,26 +87,6 @@ uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id) */ int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length); -/* Create a request to peer. - * send_public_key and send_secret_key are the pub/secret keys of the sender. - * recv_public_key is public key of reciever. - * packet must be an array of MAX_DATA_SIZE big. - * Data represents the data we send with the request with length being the length of the data. - * request_id is the id of the request (32 = friend request, 254 = ping request). - * - * return -1 on failure. - * return the length of the created packet on success. - */ -int create_request(uint8_t *send_public_key, uint8_t *send_secret_key, uint8_t *packet, uint8_t *recv_public_key, - uint8_t *data, uint32_t length, uint8_t request_id); - -/* puts the senders public key in the request in public_key, the data from the request - in data if a friend or ping request was sent to us and returns the length of the data. - packet is the request packet and length is its length - return -1 if not valid request. */ -int handle_request(uint8_t *self_public_key, uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data, - uint8_t *request_id, uint8_t *packet, uint16_t length); - /* Function to call when request beginning with byte is received. */ void cryptopacket_registerhandler(Net_Crypto *c, uint8_t byte, cryptopacket_handler_callback cb, void *object); @@ -186,15 +151,13 @@ void load_keys(Net_Crypto *c, uint8_t *keys); /* Create new instance of Net_Crypto. * Sets all the global connection variables to their default values. */ -Net_Crypto *new_net_crypto(Networking_Core *net); +Net_Crypto *new_net_crypto(DHT *dht); /* Main loop. */ void do_net_crypto(Net_Crypto *c); void kill_net_crypto(Net_Crypto *c); -/* Initialize the cryptopacket handling. */ -void init_cryptopackets(void *dht); #endif diff --git a/toxcore/onion.c b/toxcore/onion.c index c2ca21f8..8cc851c2 100644 --- a/toxcore/onion.c +++ b/toxcore/onion.c @@ -26,8 +26,6 @@ #include "onion.h" #include "util.h" -#define MAX_ONION_SIZE MAX_DATA_SIZE - #define RETURN_1 ONION_RETURN_1 #define RETURN_2 ONION_RETURN_2 #define RETURN_3 ONION_RETURN_3 @@ -89,13 +87,14 @@ int create_onion_path(DHT *dht, Onion_Path *new_path, Node_format *nodes) /* Create and send a onion packet. * * Use Onion_Path path to send data of length to dest. + * Maximum length of data is ONION_MAX_DATA_SIZE. * * return -1 on failure. * return 0 on success. */ int send_onion_packet(Networking_Core *net, Onion_Path *path, IP_Port dest, uint8_t *data, uint32_t length) { - if (1 + length + SEND_1 > MAX_ONION_SIZE || length == 0) + if (1 + length + SEND_1 > ONION_MAX_PACKET_SIZE || length == 0) return -1; to_net_family(&dest.ip); @@ -142,13 +141,18 @@ int send_onion_packet(Networking_Core *net, Onion_Path *path, IP_Port dest, uint return 0; } + /* Create and send a onion response sent initially to dest with. + * Maximum length of data is ONION_RESPONSE_MAX_DATA_SIZE. * * return -1 on failure. * return 0 on success. */ int send_onion_response(Networking_Core *net, IP_Port dest, uint8_t *data, uint32_t length, uint8_t *ret) { + if (length > ONION_RESPONSE_MAX_DATA_SIZE || length == 0) + return -1; + uint8_t packet[1 + RETURN_3 + length]; packet[0] = NET_PACKET_ONION_RECV_3; memcpy(packet + 1, ret, RETURN_3); @@ -164,7 +168,7 @@ static int handle_send_initial(void *object, IP_Port source, uint8_t *packet, ui { Onion *onion = object; - if (length > MAX_ONION_SIZE) + if (length > ONION_MAX_PACKET_SIZE) return 1; if (length <= 1 + SEND_1) @@ -172,7 +176,7 @@ static int handle_send_initial(void *object, IP_Port source, uint8_t *packet, ui change_symmetric_key(onion); - uint8_t plain[MAX_ONION_SIZE]; + uint8_t plain[ONION_MAX_PACKET_SIZE]; uint8_t shared_key[crypto_box_BEFORENMBYTES]; get_shared_key(&onion->shared_keys_1, shared_key, onion->dht->self_secret_key, packet + 1 + crypto_box_NONCEBYTES); int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, @@ -190,7 +194,7 @@ int onion_send_1(Onion *onion, uint8_t *plain, uint32_t len, IP_Port source, uin memcpy(&send_to, plain, sizeof(IP_Port)); to_host_family(&send_to.ip); - uint8_t data[MAX_ONION_SIZE]; + uint8_t data[ONION_MAX_PACKET_SIZE]; data[0] = NET_PACKET_ONION_SEND_1; memcpy(data + 1, nonce, crypto_box_NONCEBYTES); memcpy(data + 1 + crypto_box_NONCEBYTES, plain + sizeof(IP_Port), len - sizeof(IP_Port)); @@ -215,7 +219,7 @@ static int handle_send_1(void *object, IP_Port source, uint8_t *packet, uint32_t { Onion *onion = object; - if (length > MAX_ONION_SIZE) + if (length > ONION_MAX_PACKET_SIZE) return 1; if (length <= 1 + SEND_2) @@ -223,7 +227,7 @@ static int handle_send_1(void *object, IP_Port source, uint8_t *packet, uint32_t change_symmetric_key(onion); - uint8_t plain[MAX_ONION_SIZE]; + uint8_t plain[ONION_MAX_PACKET_SIZE]; uint8_t shared_key[crypto_box_BEFORENMBYTES]; get_shared_key(&onion->shared_keys_2, shared_key, onion->dht->self_secret_key, packet + 1 + crypto_box_NONCEBYTES); int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, @@ -236,7 +240,7 @@ static int handle_send_1(void *object, IP_Port source, uint8_t *packet, uint32_t memcpy(&send_to, plain, sizeof(IP_Port)); to_host_family(&send_to.ip); - uint8_t data[MAX_ONION_SIZE]; + uint8_t data[ONION_MAX_PACKET_SIZE]; data[0] = NET_PACKET_ONION_SEND_2; memcpy(data + 1, packet + 1, crypto_box_NONCEBYTES); memcpy(data + 1 + crypto_box_NONCEBYTES, plain + sizeof(IP_Port), len - sizeof(IP_Port)); @@ -264,7 +268,7 @@ static int handle_send_2(void *object, IP_Port source, uint8_t *packet, uint32_t { Onion *onion = object; - if (length > MAX_ONION_SIZE) + if (length > ONION_MAX_PACKET_SIZE) return 1; if (length <= 1 + SEND_3) @@ -272,7 +276,7 @@ static int handle_send_2(void *object, IP_Port source, uint8_t *packet, uint32_t change_symmetric_key(onion); - uint8_t plain[MAX_ONION_SIZE]; + uint8_t plain[ONION_MAX_PACKET_SIZE]; uint8_t shared_key[crypto_box_BEFORENMBYTES]; get_shared_key(&onion->shared_keys_3, shared_key, onion->dht->self_secret_key, packet + 1 + crypto_box_NONCEBYTES); int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, @@ -285,7 +289,7 @@ static int handle_send_2(void *object, IP_Port source, uint8_t *packet, uint32_t memcpy(&send_to, plain, sizeof(IP_Port)); to_host_family(&send_to.ip); - uint8_t data[MAX_ONION_SIZE]; + uint8_t data[ONION_MAX_PACKET_SIZE]; memcpy(data, plain + sizeof(IP_Port), len - sizeof(IP_Port)); uint32_t data_len = (len - sizeof(IP_Port)); uint8_t *ret_part = data + (len - sizeof(IP_Port)); @@ -312,7 +316,7 @@ static int handle_recv_3(void *object, IP_Port source, uint8_t *packet, uint32_t { Onion *onion = object; - if (length > MAX_ONION_SIZE) + if (length > ONION_MAX_PACKET_SIZE) return 1; if (length <= 1 + RETURN_3) @@ -330,7 +334,7 @@ static int handle_recv_3(void *object, IP_Port source, uint8_t *packet, uint32_t IP_Port send_to; memcpy(&send_to, plain, sizeof(IP_Port)); - uint8_t data[MAX_ONION_SIZE]; + uint8_t data[ONION_MAX_PACKET_SIZE]; data[0] = NET_PACKET_ONION_RECV_2; memcpy(data + 1, plain + sizeof(IP_Port), RETURN_2); memcpy(data + 1 + RETURN_2, packet + 1 + RETURN_3, length - (1 + RETURN_3)); @@ -346,7 +350,7 @@ static int handle_recv_2(void *object, IP_Port source, uint8_t *packet, uint32_t { Onion *onion = object; - if (length > MAX_ONION_SIZE) + if (length > ONION_MAX_PACKET_SIZE) return 1; if (length <= 1 + RETURN_2) @@ -364,7 +368,7 @@ static int handle_recv_2(void *object, IP_Port source, uint8_t *packet, uint32_t IP_Port send_to; memcpy(&send_to, plain, sizeof(IP_Port)); - uint8_t data[MAX_ONION_SIZE]; + uint8_t data[ONION_MAX_PACKET_SIZE]; data[0] = NET_PACKET_ONION_RECV_1; memcpy(data + 1, plain + sizeof(IP_Port), RETURN_1); memcpy(data + 1 + RETURN_1, packet + 1 + RETURN_2, length - (1 + RETURN_2)); @@ -380,7 +384,7 @@ static int handle_recv_1(void *object, IP_Port source, uint8_t *packet, uint32_t { Onion *onion = object; - if (length > MAX_ONION_SIZE) + if (length > ONION_MAX_PACKET_SIZE) return 1; if (length <= 1 + RETURN_1) @@ -424,7 +428,7 @@ Onion *new_onion(DHT *dht) return NULL; onion->dht = dht; - onion->net = dht->c->lossless_udp->net; + onion->net = dht->net; new_symmetric_key(onion->secret_symmetric_key); onion->timestamp = unix_time(); diff --git a/toxcore/onion.h b/toxcore/onion.h index b15caad9..712bbf13 100644 --- a/toxcore/onion.h +++ b/toxcore/onion.h @@ -39,6 +39,8 @@ typedef struct { void *callback_object; } Onion; +#define ONION_MAX_PACKET_SIZE 1400 + #define ONION_RETURN_1 (crypto_box_NONCEBYTES + sizeof(IP_Port) + crypto_box_MACBYTES) #define ONION_RETURN_2 (crypto_box_NONCEBYTES + sizeof(IP_Port) + crypto_box_MACBYTES + ONION_RETURN_1) #define ONION_RETURN_3 (crypto_box_NONCEBYTES + sizeof(IP_Port) + crypto_box_MACBYTES + ONION_RETURN_2) @@ -48,6 +50,9 @@ typedef struct { #define ONION_SEND_2 (crypto_box_NONCEBYTES + ONION_SEND_BASE*2 + ONION_RETURN_1) #define ONION_SEND_1 (crypto_box_NONCEBYTES + ONION_SEND_BASE*3) +#define ONION_MAX_DATA_SIZE (ONION_MAX_PACKET_SIZE - (ONION_SEND_1 + 1)) +#define ONION_RESPONSE_MAX_DATA_SIZE (ONION_MAX_PACKET_SIZE - (1 + ONION_RETURN_3)) + typedef struct { uint8_t shared_key1[crypto_box_BEFORENMBYTES]; uint8_t shared_key2[crypto_box_BEFORENMBYTES]; @@ -76,6 +81,7 @@ int create_onion_path(DHT *dht, Onion_Path *new_path, Node_format *nodes); /* Create and send a onion packet. * * Use Onion_Path path to send data of length to dest. + * Maximum length of data is ONION_MAX_DATA_SIZE. * * return -1 on failure. * return 0 on success. @@ -83,6 +89,7 @@ int create_onion_path(DHT *dht, Onion_Path *new_path, Node_format *nodes); int send_onion_packet(Networking_Core *net, Onion_Path *path, IP_Port dest, uint8_t *data, uint32_t length); /* Create and send a onion response sent initially to dest with. + * Maximum length of data is ONION_RESPONSE_MAX_DATA_SIZE. * * return -1 on failure. * return 0 on success. diff --git a/toxcore/onion_announce.c b/toxcore/onion_announce.c index 5bab931a..1e73aef9 100644 --- a/toxcore/onion_announce.c +++ b/toxcore/onion_announce.c @@ -32,7 +32,7 @@ #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) +#define DATA_REQUEST_MIN_SIZE ONION_DATA_REQUEST_MIN_SIZE #define DATA_REQUEST_MIN_SIZE_RECV (DATA_REQUEST_MIN_SIZE + ONION_RETURN_3) /* Create and send an onion announce request packet. @@ -90,6 +90,9 @@ int send_announce_request(Networking_Core *net, Onion_Path *path, Node_format de int send_data_request(Networking_Core *net, Onion_Path *path, IP_Port dest, uint8_t *public_key, uint8_t *encrypt_public_key, uint8_t *nonce, uint8_t *data, uint16_t length) { + if (DATA_REQUEST_MIN_SIZE + length > ONION_MAX_DATA_SIZE) + return -1; + uint8_t packet[DATA_REQUEST_MIN_SIZE + length]; packet[0] = NET_PACKET_ONION_DATA_REQUEST; memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES); @@ -304,7 +307,7 @@ static int handle_data_request(void *object, IP_Port source, uint8_t *packet, ui if (length <= DATA_REQUEST_MIN_SIZE_RECV) return 1; - if (length >= MAX_DATA_SIZE) + if (length > ONION_MAX_PACKET_SIZE) return 1; int index = in_entries(onion_a, packet + 1); diff --git a/toxcore/onion_announce.h b/toxcore/onion_announce.h index 071dc9ff..dff61e99 100644 --- a/toxcore/onion_announce.h +++ b/toxcore/onion_announce.h @@ -40,6 +40,9 @@ #error announce response packets assume that ONION_PING_ID_SIZE is equal to crypto_box_PUBLICKEYBYTES #endif +#define ONION_DATA_REQUEST_MIN_SIZE (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES) +#define MAX_DATA_REQUEST_SIZE (ONION_MAX_DATA_SIZE - ONION_DATA_REQUEST_MIN_SIZE) + typedef struct { uint8_t public_key[crypto_box_PUBLICKEYBYTES]; IP_Port ret_ip_port; @@ -86,6 +89,8 @@ int send_announce_request(Networking_Core *net, Onion_Path *path, Node_format de * * nonce is the nonce to encrypt this packet with * + * The maximum length of data is MAX_DATA_REQUEST_SIZE. + * * return -1 on failure. * return 0 on success. */ diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index fbb00a2c..35fb4423 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c @@ -183,9 +183,9 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_ if (random_path(onion_c->dht, &onion_c->onion_paths, pathnum, &path) == -1) return -1; - return send_announce_request(onion_c->net, &path, dest_node, onion_c->dht->c->self_public_key, - onion_c->dht->c->self_secret_key, ping_id, - onion_c->dht->c->self_public_key, onion_c->temp_public_key, sendback); + return send_announce_request(onion_c->net, &path, dest_node, onion_c->c->self_public_key, + onion_c->c->self_secret_key, ping_id, + onion_c->c->self_public_key, onion_c->temp_public_key, sendback); } else { if (random_path(onion_c->dht, &onion_c->friends_list[num - 1].onion_paths, pathnum, &path) == -1) return -1; @@ -236,7 +236,7 @@ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, uint8_t *publ if (num == 0) { list_nodes = onion_c->clients_announce_list; - reference_id = onion_c->dht->c->self_public_key; + reference_id = onion_c->c->self_public_key; if (is_stored && memcmp(pingid_or_key, onion_c->temp_public_key, crypto_box_PUBLICKEYBYTES) != 0) { is_stored = 0; @@ -325,7 +325,7 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, Node_format *n if (num == 0) { list_nodes = onion_c->clients_announce_list; - reference_id = onion_c->dht->c->self_public_key; + reference_id = onion_c->c->self_public_key; ping_nodes_sent_second = &onion_c->ping_nodes_sent_second; last_pinged = onion_c->last_pinged; last_pinged_index = &onion_c->last_pinged_index; @@ -388,7 +388,7 @@ static int handle_announce_response(void *object, IP_Port source, uint8_t *packe int len = -1; if (num == 0) { - len = decrypt_data(public_key, onion_c->dht->c->self_secret_key, packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH, + len = decrypt_data(public_key, onion_c->c->self_secret_key, packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH, packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES, length - (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES), plain); } else { @@ -421,7 +421,7 @@ 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) +#define DATA_IN_RESPONSE_MIN_SIZE ONION_DATA_IN_RESPONSE_MIN_SIZE static int handle_data_response(void *object, IP_Port source, uint8_t *packet, uint32_t length) { @@ -430,7 +430,7 @@ static int handle_data_response(void *object, IP_Port source, uint8_t *packet, u if (length <= (ONION_DATA_RESPONSE_MIN_SIZE + DATA_IN_RESPONSE_MIN_SIZE)) return 1; - if (length > MAX_DATA_SIZE) + if (length > MAX_DATA_REQUEST_SIZE) return 1; uint8_t temp_plain[length - ONION_DATA_RESPONSE_MIN_SIZE]; @@ -442,7 +442,7 @@ static int handle_data_response(void *object, IP_Port source, uint8_t *packet, u 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, + len = decrypt_data(temp_plain, onion_c->c->self_secret_key, packet + 1, temp_plain + crypto_box_PUBLICKEYBYTES, sizeof(temp_plain) - crypto_box_PUBLICKEYBYTES, plain); if ((uint32_t)len != sizeof(plain)) @@ -527,7 +527,7 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, uint8_t *data, uint32 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) + if (length + DATA_IN_RESPONSE_MIN_SIZE > MAX_DATA_REQUEST_SIZE) return -1; if (length == 0) @@ -537,8 +537,8 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, uint8_t *data, uint32 random_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, + memcpy(packet, onion_c->c->self_public_key, crypto_box_PUBLICKEYBYTES); + int len = encrypt_data(onion_c->friends_list[friend_num].real_client_id, onion_c->c->self_secret_key, nonce, data, length, packet + crypto_box_PUBLICKEYBYTES); if ((uint32_t)len + crypto_box_PUBLICKEYBYTES != sizeof(packet)) @@ -597,15 +597,15 @@ static int send_dht_fakeid(Onion_Client *onion_c, int friend_num, uint8_t *data, 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, onion_c->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, + int len = encrypt_data(onion_c->friends_list[friend_num].real_client_id, onion_c->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]; + uint8_t packet[MAX_CRYPTO_REQUEST_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); @@ -626,7 +626,7 @@ static int handle_dht_fakeid(void *object, IP_Port source, uint8_t *source_pubke 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, + int len = decrypt_data(packet, onion_c->c->self_secret_key, packet + crypto_box_PUBLICKEYBYTES, packet + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, length - (crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES), plain); @@ -960,7 +960,7 @@ static void do_announce(Onion_Client *onion_c) if (count != MAX_ONION_CLIENTS) { if (count < (uint32_t)rand() % MAX_ONION_CLIENTS) { 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, + uint32_t num_nodes = get_close_nodes(onion_c->dht, onion_c->c->self_public_key, nodes_list, rand() % 2 ? AF_INET : AF_INET6, 1, 0); for (i = 0; i < num_nodes; ++i) { @@ -989,9 +989,9 @@ void do_onion_client(Onion_Client *onion_c) onion_c->last_run = unix_time(); } -Onion_Client *new_onion_client(DHT *dht) +Onion_Client *new_onion_client(Net_Crypto *c) { - if (dht == NULL) + if (c == NULL) return NULL; Onion_Client *onion_c = calloc(1, sizeof(Onion_Client)); @@ -999,14 +999,15 @@ Onion_Client *new_onion_client(DHT *dht) if (onion_c == NULL) return NULL; - onion_c->dht = dht; - onion_c->net = dht->c->lossless_udp->net; + onion_c->dht = c->dht; + onion_c->net = c->dht->net; + onion_c->c = c; 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); + cryptopacket_registerhandler(onion_c->c, FAKEID_DATA_ID, &handle_dht_fakeid, onion_c); return onion_c; } @@ -1020,7 +1021,7 @@ void kill_onion_client(Onion_Client *onion_c) networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, NULL, NULL); networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, NULL, NULL); oniondata_registerhandler(onion_c, FAKEID_DATA_ID, NULL, NULL); - cryptopacket_registerhandler(onion_c->dht->c, FAKEID_DATA_ID, NULL, NULL); + cryptopacket_registerhandler(onion_c->c, FAKEID_DATA_ID, NULL, NULL); memset(onion_c, 0, sizeof(Onion_Client)); free(onion_c); } diff --git a/toxcore/onion_client.h b/toxcore/onion_client.h index 8e09b63a..6b960e40 100644 --- a/toxcore/onion_client.h +++ b/toxcore/onion_client.h @@ -25,6 +25,7 @@ #define ONION_CLIENT_H #include "onion_announce.h" +#include "net_crypto.h" #define MAX_ONION_CLIENTS 8 #define ONION_NODE_PING_INTERVAL 30 @@ -105,6 +106,7 @@ typedef int (*oniondata_handler_callback)(void *object, uint8_t *source_pubkey, typedef struct { DHT *dht; + Net_Crypto *c; Networking_Core *net; Onion_Friend *friends_list; uint16_t num_friends; @@ -170,8 +172,11 @@ int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_on */ int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port); +#define ONION_DATA_IN_RESPONSE_MIN_SIZE (crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES) +#define ONION_CLIENT_MAX_DATA_SIZE (MAX_DATA_REQUEST_SIZE - ONION_DATA_IN_RESPONSE_MIN_SIZE) /* Send data of length length to friendnum. + * Maximum length of data is ONION_CLIENT_MAX_DATA_SIZE. * 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. @@ -186,7 +191,7 @@ void oniondata_registerhandler(Onion_Client *onion_c, uint8_t byte, oniondata_ha void do_onion_client(Onion_Client *onion_c); -Onion_Client *new_onion_client(DHT *dht); +Onion_Client *new_onion_client(Net_Crypto *c); void kill_onion_client(Onion_Client *onion_c); From 0559904ea28c026baed4a62ff39b8280cd63e58a Mon Sep 17 00:00:00 2001 From: irungentoo Date: Wed, 23 Apr 2014 12:29:24 -0400 Subject: [PATCH 027/117] Updated some files so that they could build with latest core. Fixed some issues. --- auto_tests/onion_test.c | 34 +++++++++++++++++----------------- other/DHT_bootstrap.c | 23 +++++++++-------------- testing/DHT_test.c | 6 ++---- toxcore/DHT.h | 4 ++++ toxcore/net_crypto.h | 3 --- toxcore/onion_announce.c | 2 +- toxcore/onion_client.c | 4 ++-- 7 files changed, 35 insertions(+), 41 deletions(-) diff --git a/auto_tests/onion_test.c b/auto_tests/onion_test.c index cd060b1f..b8145cc2 100644 --- a/auto_tests/onion_test.c +++ b/auto_tests/onion_test.c @@ -80,7 +80,7 @@ static int handle_test_3(void *object, IP_Port source, uint8_t *packet, uint32_t 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, + int len = decrypt_data(test_3_pub_key, onion->dht->self_secret_key, packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH, packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES, 1 + crypto_hash_sha256_BYTES + crypto_box_MACBYTES, plain); @@ -111,7 +111,7 @@ static int handle_test_4(void *object, IP_Port source, uint8_t *packet, uint32_t 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, + int len = decrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion->dht->self_secret_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, sizeof("Install gentoo") + crypto_box_MACBYTES, plain); if (len == -1) @@ -129,8 +129,8 @@ START_TEST(test_basic) IP ip; ip_init(&ip, 1); ip.ip6.uint8[15] = 1; - Onion *onion1 = new_onion(new_DHT(new_net_crypto(new_networking(ip, 34567)))); - Onion *onion2 = new_onion(new_DHT(new_net_crypto(new_networking(ip, 34568)))); + Onion *onion1 = new_onion(new_DHT(new_networking(ip, 34567))); + Onion *onion2 = new_onion(new_DHT(new_networking(ip, 34568))); ck_assert_msg((onion1 != NULL) && (onion2 != NULL), "Onion failed initializing."); networking_registerhandler(onion2->net, 'I', &handle_test_1, onion2); @@ -177,9 +177,9 @@ START_TEST(test_basic) uint8_t zeroes[64] = {0}; randombytes(sb_data, sizeof(sb_data)); memcpy(test_3_pub_key, nodes[3].client_id, crypto_box_PUBLICKEYBYTES); - ret = send_announce_request(onion1->net, &path, nodes[3], onion1->dht->c->self_public_key, - onion1->dht->c->self_secret_key, - zeroes, onion1->dht->c->self_public_key, onion1->dht->c->self_public_key, sb_data); + ret = send_announce_request(onion1->net, &path, nodes[3], onion1->dht->self_public_key, + onion1->dht->self_secret_key, + zeroes, onion1->dht->self_public_key, onion1->dht->self_public_key, sb_data); ck_assert_msg(ret == 0, "Failed to create/send onion announce_request packet."); handled_test_3 = 0; @@ -193,10 +193,10 @@ START_TEST(test_basic) memcpy(onion2_a->entries[1].public_key, onion2->dht->self_public_key, crypto_box_PUBLICKEYBYTES); onion2_a->entries[1].time = unix_time(); networking_registerhandler(onion1->net, NET_PACKET_ONION_DATA_RESPONSE, &handle_test_4, onion1); - send_announce_request(onion1->net, &path, nodes[3], onion1->dht->c->self_public_key, onion1->dht->c->self_secret_key, - test_3_ping_id, onion1->dht->c->self_public_key, onion1->dht->c->self_public_key, sb_data); + send_announce_request(onion1->net, &path, nodes[3], onion1->dht->self_public_key, onion1->dht->self_secret_key, + test_3_ping_id, onion1->dht->self_public_key, onion1->dht->self_public_key, sb_data); - while (memcmp(onion2_a->entries[ONION_ANNOUNCE_MAX_ENTRIES - 2].public_key, onion1->dht->c->self_public_key, + while (memcmp(onion2_a->entries[ONION_ANNOUNCE_MAX_ENTRIES - 2].public_key, onion1->dht->self_public_key, crypto_box_PUBLICKEYBYTES) != 0) { do_onion(onion1); do_onion(onion2); @@ -204,12 +204,12 @@ START_TEST(test_basic) } c_sleep(1000); - Onion *onion3 = new_onion(new_DHT(new_net_crypto(new_networking(ip, 34569)))); + Onion *onion3 = new_onion(new_DHT(new_networking(ip, 34569))); ck_assert_msg((onion3 != NULL), "Onion failed initializing."); new_nonce(nonce); - ret = send_data_request(onion3->net, &path, nodes[3].ip_port, onion1->dht->c->self_public_key, - onion1->dht->c->self_public_key, + ret = send_data_request(onion3->net, &path, nodes[3].ip_port, onion1->dht->self_public_key, + onion1->dht->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; @@ -234,10 +234,10 @@ Onions *new_onions(uint16_t port) ip_init(&ip, 1); ip.ip6.uint8[15] = 1; Onions *on = malloc(sizeof(Onions)); - DHT *dht = new_DHT(new_net_crypto(new_networking(ip, port))); + DHT *dht = new_DHT(new_networking(ip, port)); on->onion = new_onion(dht); on->onion_a = new_onion_announce(dht); - on->onion_c = new_onion_client(dht); + on->onion_c = new_onion_client(new_net_crypto(dht)); if (on->onion && on->onion_a && on->onion_c) return on; @@ -298,8 +298,8 @@ START_TEST(test_announce) c_sleep(50); } - onion_addfriend(onions[7]->onion_c, onions[37]->onion->dht->c->self_public_key); - int frnum = onion_addfriend(onions[37]->onion_c, onions[7]->onion->dht->c->self_public_key); + onion_addfriend(onions[7]->onion_c, onions[37]->onion_c->c->self_public_key); + int frnum = onion_addfriend(onions[37]->onion_c, onions[7]->onion_c->c->self_public_key); int ok = -1; diff --git a/other/DHT_bootstrap.c b/other/DHT_bootstrap.c index 738c2a0c..462360c3 100644 --- a/other/DHT_bootstrap.c +++ b/other/DHT_bootstrap.c @@ -75,11 +75,12 @@ void manage_keys(DHT *dht) exit(1); } - load_keys(dht->c, keys); + memcpy(dht->self_public_key, keys, crypto_box_PUBLICKEYBYTES); + memcpy(dht->self_secret_key, keys + crypto_box_PUBLICKEYBYTES, crypto_box_SECRETKEYBYTES); printf("Keys loaded successfully.\n"); } else { - new_keys(dht->c); - save_keys(dht->c, keys); + memcpy(keys, dht->self_public_key, crypto_box_PUBLICKEYBYTES); + memcpy(keys + crypto_box_PUBLICKEYBYTES, dht->self_secret_key, crypto_box_SECRETKEYBYTES); keys_file = fopen("key", "w"); if (fwrite(keys, sizeof(uint8_t), KEYS_SIZE, keys_file) != KEYS_SIZE) { @@ -113,7 +114,7 @@ int main(int argc, char *argv[]) IP ip; ip_init(&ip, ipv6enabled); - DHT *dht = new_DHT(new_net_crypto(new_networking(ip, PORT))); + DHT *dht = new_DHT(new_networking(ip, PORT)); Onion *onion = new_onion(dht); Onion_Announce *onion_a = new_onion_announce(dht); @@ -129,9 +130,6 @@ int main(int argc, char *argv[]) perror("Initialization"); manage_keys(dht); - /* We want our DHT public key to be the same as our internal one since this is a bootstrap node */ - 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; @@ -151,17 +149,14 @@ int main(int argc, char *argv[]) file = fopen("PUBLIC_ID.txt", "w"); for (i = 0; i < 32; i++) { - if (dht->c->self_public_key[i] < 16) - printf("0"); - - printf("%hhX", dht->c->self_public_key[i]); - fprintf(file, "%hhX", dht->c->self_public_key[i]); + printf("%02hhX", dht->self_public_key[i]); + fprintf(file, "%02hhX", dht->self_public_key[i]); } fclose(file); printf("\n"); - printf("Port: %u\n", ntohs(dht->c->lossless_udp->net->port)); + printf("Port: %u\n", ntohs(dht->net->port)); if (argc > argvoffset + 3) { printf("Trying to bootstrap into the network...\n"); @@ -198,7 +193,7 @@ int main(int argc, char *argv[]) #ifdef TCP_RELAY_ENABLED do_TCP_server(tcp_s); #endif - networking_poll(dht->c->lossless_udp->net); + networking_poll(dht->net); c_sleep(1); } diff --git a/testing/DHT_test.c b/testing/DHT_test.c index 3f8b58bd..2636ed02 100644 --- a/testing/DHT_test.c +++ b/testing/DHT_test.c @@ -187,9 +187,7 @@ int main(int argc, char *argv[]) IP ip; ip_init(&ip, ipv6enabled); - DHT *dht = new_DHT(new_net_crypto(new_networking(ip, PORT))); - - new_keys(dht->c); + DHT *dht = new_DHT(new_networking(ip, PORT)); printf("OUR ID: "); uint32_t i; @@ -245,7 +243,7 @@ int main(int argc, char *argv[]) } } */ - networking_poll(dht->c->lossless_udp->net); + networking_poll(dht->net); print_clientlist(dht); print_friendlist(dht); diff --git a/toxcore/DHT.h b/toxcore/DHT.h index c08b498c..c0731a3a 100644 --- a/toxcore/DHT.h +++ b/toxcore/DHT.h @@ -337,6 +337,10 @@ int route_packet(DHT *dht, uint8_t *client_id, uint8_t *packet, uint32_t length) */ int route_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint32_t length); +/* Function to handle crypto packets. + */ +void cryptopacket_registerhandler(DHT *dht, uint8_t byte, cryptopacket_handler_callback cb, void *object); + /* NAT PUNCHING FUNCTIONS */ /* Puts all the different ips returned by the nodes for a friend_id into array ip_portlist. diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index ef56b304..b2b9f4f5 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -87,9 +87,6 @@ uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id) */ int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length); -/* Function to call when request beginning with byte is received. */ -void cryptopacket_registerhandler(Net_Crypto *c, uint8_t byte, cryptopacket_handler_callback cb, void *object); - /* Start a secure connection with other peer who has public_key and ip_port. * * return -1 if failure. diff --git a/toxcore/onion_announce.c b/toxcore/onion_announce.c index 1e73aef9..abe72486 100644 --- a/toxcore/onion_announce.c +++ b/toxcore/onion_announce.c @@ -90,7 +90,7 @@ int send_announce_request(Networking_Core *net, Onion_Path *path, Node_format de int send_data_request(Networking_Core *net, Onion_Path *path, IP_Port dest, uint8_t *public_key, uint8_t *encrypt_public_key, uint8_t *nonce, uint8_t *data, uint16_t length) { - if (DATA_REQUEST_MIN_SIZE + length > ONION_MAX_DATA_SIZE) + if ((unsigned int)DATA_REQUEST_MIN_SIZE + length > ONION_MAX_DATA_SIZE) return -1; uint8_t packet[DATA_REQUEST_MIN_SIZE + length]; diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index 35fb4423..ee902d99 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c @@ -1007,7 +1007,7 @@ Onion_Client *new_onion_client(Net_Crypto *c) 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->c, FAKEID_DATA_ID, &handle_dht_fakeid, onion_c); + cryptopacket_registerhandler(onion_c->dht, FAKEID_DATA_ID, &handle_dht_fakeid, onion_c); return onion_c; } @@ -1021,7 +1021,7 @@ void kill_onion_client(Onion_Client *onion_c) networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, NULL, NULL); networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, NULL, NULL); oniondata_registerhandler(onion_c, FAKEID_DATA_ID, NULL, NULL); - cryptopacket_registerhandler(onion_c->c, FAKEID_DATA_ID, NULL, NULL); + cryptopacket_registerhandler(onion_c->dht, FAKEID_DATA_ID, NULL, NULL); memset(onion_c, 0, sizeof(Onion_Client)); free(onion_c); } From 2aa3cdfc6908bd56bc8797017ae1c3a399e73c9f Mon Sep 17 00:00:00 2001 From: irungentoo Date: Wed, 23 Apr 2014 12:47:57 -0400 Subject: [PATCH 028/117] Fixed the DHT bootstrap daemon. --- other/bootstrap_daemon/tox_bootstrap_daemon.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/other/bootstrap_daemon/tox_bootstrap_daemon.c b/other/bootstrap_daemon/tox_bootstrap_daemon.c index 66f6436d..abad7760 100644 --- a/other/bootstrap_daemon/tox_bootstrap_daemon.c +++ b/other/bootstrap_daemon/tox_bootstrap_daemon.c @@ -36,9 +36,9 @@ #include "config.h" #endif -#include "../../toxcore/DHT.h" -#include "../../toxcore/friend_requests.h" +#include "../../toxcore/onion_announce.h" #include "../../toxcore/LAN_discovery.h" +#include "../../toxcore/util.h" #include "../../testing/misc_tools.c" @@ -75,11 +75,12 @@ int manage_keys(DHT *dht, char *keys_file_path) return 0; } - load_keys(dht->c, keys); + memcpy(dht->self_public_key, keys, crypto_box_PUBLICKEYBYTES); + memcpy(dht->self_secret_key, keys + crypto_box_PUBLICKEYBYTES, crypto_box_SECRETKEYBYTES); } else { // Otherwise save new keys - new_keys(dht->c); - save_keys(dht->c, keys); + memcpy(keys, dht->self_public_key, crypto_box_PUBLICKEYBYTES); + memcpy(keys + crypto_box_PUBLICKEYBYTES, dht->self_secret_key, crypto_box_SECRETKEYBYTES); keys_file = fopen(keys_file_path, "w"); @@ -92,10 +93,6 @@ int manage_keys(DHT *dht, char *keys_file_path) fclose(keys_file); - // We want our DHT public key to be the same as our internal one since this is a bootstrap node - 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); - return 1; } @@ -351,7 +348,7 @@ int main(int argc, char *argv[]) IP ip; ip_init(&ip, enable_ipv6); - DHT *dht = new_DHT(new_net_crypto(new_networking(ip, port))); + DHT *dht = new_DHT(new_networking(ip, port)); if (dht == NULL) { syslog(LOG_ERR, "Couldn't initialize Tox DHT instance. Exiting.\n"); @@ -384,7 +381,7 @@ int main(int argc, char *argv[]) return 1; } - print_public_key(dht->c->self_public_key); + print_public_key(dht->self_public_key); // Write the PID file FILE *pidf = fopen(pid_file_path, "w"); From 2b283535544aab26840dae6eaa2a1df07f6b60c9 Mon Sep 17 00:00:00 2001 From: stal Date: Wed, 23 Apr 2014 17:29:50 -0700 Subject: [PATCH 029/117] Properly deallocate friends' status messages in kill_messenger Lightly tested. I'm not sure whether this creates a double-free bug --- toxcore/Messenger.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 752b164d..9cc3b744 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -1816,6 +1816,10 @@ void kill_messenger(Messenger *m) kill_DHT(m->dht); kill_net_crypto(m->net_crypto); kill_networking(m->net); + for (i = 0; i < m->numfriends; ++i) { + if (m->friendlist[i].statusmessage) + free(m->friendlist[i].statusmessage); + } free(m->friendlist); free(m); } From 78cbb287b189753bc1f961769637fe27b44377a0 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 24 Apr 2014 21:02:36 -0400 Subject: [PATCH 030/117] sendnodes packets now contains a byte indicating the number of nodes --- toxcore/DHT.c | 46 +++++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/toxcore/DHT.c b/toxcore/DHT.c index 8b553581..c6c83387 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c @@ -240,11 +240,11 @@ int pack_nodes(uint8_t *data, uint16_t length, Node_format *nodes, uint16_t numb * return number of unpacked nodes on success. * return -1 on failure. */ -int unpack_nodes(Node_format *nodes, uint16_t size, uint8_t *data, uint16_t length) +int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint8_t *data, uint16_t length) { uint32_t num = 0, len_processed = 0; - while (num < size && len_processed < length) { + while (num < max_num_nodes && len_processed < length) { if (data[len_processed] == TOX_AF_INET) { uint32_t size = 1 + sizeof(IP4) + sizeof(uint16_t) + CLIENT_ID_SIZE; @@ -992,15 +992,18 @@ static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cli /* Send a send nodes response: message for IPv6 nodes */ static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint8_t *encrypted_data, - uint8_t *shared_encryption_key) + uint16_t length, uint8_t *shared_encryption_key) { /* Check if packet is going to be sent to ourself. */ if (id_equal(public_key, dht->self_public_key)) return -1; + if (length > NODES_ENCRYPTED_MESSAGE_LENGTH || length == 0) + return -1; + size_t Node_format_size = sizeof(Node_format); uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES - + Node_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES]; + + Node_format_size * MAX_SENT_NODES + length + crypto_box_MACBYTES]; Node_format nodes_list[MAX_SENT_NODES]; uint32_t num_nodes = get_close_nodes(dht, client_id, nodes_list, 0, LAN_ip(ip_port.ip) == 0, 1); @@ -1008,24 +1011,25 @@ static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_ if (num_nodes == 0) return 0; - uint8_t plain[Node_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH]; - uint8_t encrypt[Node_format_size * MAX_SENT_NODES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES]; + uint8_t plain[1 + Node_format_size * MAX_SENT_NODES + length]; + uint8_t encrypt[sizeof(plain) + crypto_box_MACBYTES]; uint8_t nonce[crypto_box_NONCEBYTES]; new_nonce(nonce); - int nodes_length = pack_nodes(plain, Node_format_size * MAX_SENT_NODES, nodes_list, num_nodes); + int nodes_length = pack_nodes(plain + 1, Node_format_size * MAX_SENT_NODES, nodes_list, num_nodes); if (nodes_length <= 0) return -1; - memcpy(plain + nodes_length, encrypted_data, NODES_ENCRYPTED_MESSAGE_LENGTH); + plain[0] = num_nodes; + memcpy(plain + 1 + nodes_length, encrypted_data, length); int len = encrypt_data_symmetric( shared_encryption_key, nonce, plain, - nodes_length + NODES_ENCRYPTED_MESSAGE_LENGTH, + 1 + nodes_length + length, encrypt ); - if ((unsigned int)len != nodes_length + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES) + if (len != 1 + nodes_length + length + crypto_box_MACBYTES) return -1; data[0] = NET_PACKET_SEND_NODES_IPV6; @@ -1061,7 +1065,7 @@ static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32 if (len != CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH) return 1; - sendnodes_ipv6(dht, source, packet + 1, plain, plain + CLIENT_ID_SIZE, shared_key); + sendnodes_ipv6(dht, source, packet + 1, plain, plain + CLIENT_ID_SIZE, NODES_ENCRYPTED_MESSAGE_LENGTH, shared_key); add_to_ping(dht->ping, packet + 1, source); @@ -1105,7 +1109,8 @@ static int handle_sendnodes_core(void *object, IP_Port source, uint8_t *packet, Node_format *plain_nodes, uint16_t size_plain_nodes, uint32_t *num_nodes_out) { DHT *dht = object; - uint32_t cid_size = 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES; + uint32_t cid_size = 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + 1 + NODES_ENCRYPTED_MESSAGE_LENGTH + + crypto_box_MACBYTES; if (length <= cid_size) /* too short */ return 1; @@ -1118,25 +1123,28 @@ static int handle_sendnodes_core(void *object, IP_Port source, uint8_t *packet, if (data_size > sizeof(Node_format) * MAX_SENT_NODES) /* invalid length */ return 1; - uint8_t plain[data_size + NODES_ENCRYPTED_MESSAGE_LENGTH]; + uint8_t plain[1 + data_size + NODES_ENCRYPTED_MESSAGE_LENGTH]; uint8_t shared_key[crypto_box_BEFORENMBYTES]; DHT_get_shared_key_sent(dht, shared_key, packet + 1); int len = decrypt_data_symmetric( shared_key, packet + 1 + CLIENT_ID_SIZE, packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, - data_size + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES, + 1 + data_size + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES, plain); if ((unsigned int)len != sizeof(plain)) return 1; - Node_format sendback_node; - - if (!sent_getnode_to_node(dht, packet + 1, source, plain + data_size, &sendback_node)) + if (plain[0] > size_plain_nodes || plain[0] == 0) return 1; - int num_nodes = unpack_nodes(plain_nodes, size_plain_nodes, plain, data_size); + Node_format sendback_node; + + if (!sent_getnode_to_node(dht, packet + 1, source, plain + 1 + data_size, &sendback_node)) + return 1; + + int num_nodes = unpack_nodes(plain_nodes, plain[0], plain + 1, data_size); if (num_nodes <= 0) return 1; @@ -1146,7 +1154,7 @@ static int handle_sendnodes_core(void *object, IP_Port source, uint8_t *packet, *num_nodes_out = num_nodes; - send_hardening_getnode_res(dht, &sendback_node, packet + 1, plain, data_size); + send_hardening_getnode_res(dht, &sendback_node, packet + 1, plain + 1, data_size); return 0; } From a79eafbb5292b5fb5ae677c97a9bf2ecc4f853b0 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 25 Apr 2014 09:02:49 -0400 Subject: [PATCH 031/117] The data in the DHT get nodes and send nodes packets can now be of variable length. --- docs/updates/DHT.md | 4 ++-- toxcore/DHT.c | 44 +++++++++++++++++++++++++++++------------- toxcore/DHT.h | 6 ++++-- toxcore/onion_client.c | 5 +++-- 4 files changed, 40 insertions(+), 19 deletions(-) diff --git a/docs/updates/DHT.md b/docs/updates/DHT.md index 9e94ab11..ba6abe3a 100644 --- a/docs/updates/DHT.md +++ b/docs/updates/DHT.md @@ -95,11 +95,11 @@ ping_id = a random integer, the response must contain the exact same number as t Get nodes (Request): Packet contents: ``` -[byte with value: 02][char array (client node_id), length=32 bytes][random 24 byte nonce][Encrypted with the nonce and private key of the sender:[char array: requested_node_id (node_id of which we want the ip), length=32 bytes][Encrypted data (must be sent back unmodified by in the response), length=NODES_ENCRYPTED_MESSAGE_LENGTH bytes]] +[byte with value: 02][char array (client node_id), length=32 bytes][random 24 byte nonce][Encrypted with the nonce and private key of the sender:[char array: requested_node_id (node_id of which we want the ip), length=32 bytes][Sendback data (must be sent back unmodified by in the response), length=1 to NODES_ENCRYPTED_MESSAGE_LENGTH bytes]] ``` Valid replies: a send_nodes packet Send_nodes (response (for all addresses)): ``` -[byte with value: 04][char array (client node_id), length=32 bytes][random 24 byte nonce][Encrypted with the nonce and private key of the sender:[Nodes in node format, length=?? * (number of nodes (maximum of 8 nodes)) bytes][Encrypted data, length=NODES_ENCRYPTED_MESSAGE_LENGTH bytes]] +[byte with value: 04][char array (client node_id), length=32 bytes][random 24 byte nonce][Encrypted with the nonce and private key of the sender:[uint8_t number of nodes in this packet][Nodes in node format, length=?? * (number of nodes (maximum of 8 nodes)) bytes][Sendback data, length=1 to NODES_ENCRYPTED_MESSAGE_LENGTH bytes]] ``` diff --git a/toxcore/DHT.c b/toxcore/DHT.c index c6c83387..4e33c02e 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c @@ -235,12 +235,14 @@ int pack_nodes(uint8_t *data, uint16_t length, Node_format *nodes, uint16_t numb return packed_length; } -/* Unpack data of length into nodes of size (in number of nodes). +/* Unpack data of length into nodes of size max_num_nodes. + * Put the length of the data processed in processed_data_len. * * return number of unpacked nodes on success. * return -1 on failure. */ -int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint8_t *data, uint16_t length) +int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint16_t *processed_data_len, uint8_t *data, + uint16_t length) { uint32_t num = 0, len_processed = 0; @@ -274,6 +276,9 @@ int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint8_t *data, uint } } + if (processed_data_len) + *processed_data_len = len_processed; + return num; } @@ -991,7 +996,7 @@ static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cli } /* Send a send nodes response: message for IPv6 nodes */ -static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint8_t *encrypted_data, +static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint8_t *sendback_data, uint16_t length, uint8_t *shared_encryption_key) { /* Check if packet is going to be sent to ourself. */ @@ -1022,7 +1027,7 @@ static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_ return -1; plain[0] = num_nodes; - memcpy(plain + 1 + nodes_length, encrypted_data, length); + memcpy(plain + 1 + nodes_length, sendback_data, length); int len = encrypt_data_symmetric( shared_encryption_key, nonce, plain, @@ -1042,30 +1047,36 @@ static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_ static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length) { - DHT *dht = object; + uint32_t cmp_len = 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + CLIENT_ID_SIZE + crypto_box_MACBYTES; - if (length != ( 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH + - crypto_box_MACBYTES )) + if (length <= cmp_len) return 1; + if (length > cmp_len + NODES_ENCRYPTED_MESSAGE_LENGTH) + return 1; + + uint16_t sendback_data_length = length - cmp_len; + + DHT *dht = object; + /* Check if packet is from ourself. */ if (id_equal(packet + 1, dht->self_public_key)) return 1; - uint8_t plain[CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH]; + uint8_t plain[CLIENT_ID_SIZE + sendback_data_length]; uint8_t shared_key[crypto_box_BEFORENMBYTES]; DHT_get_shared_key_recv(dht, shared_key, packet + 1); int len = decrypt_data_symmetric( shared_key, packet + 1 + CLIENT_ID_SIZE, packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, - CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES, + CLIENT_ID_SIZE + sendback_data_length + crypto_box_MACBYTES, plain ); - if (len != CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH) + if (len != CLIENT_ID_SIZE + sendback_data_length) return 1; - sendnodes_ipv6(dht, source, packet + 1, plain, plain + CLIENT_ID_SIZE, NODES_ENCRYPTED_MESSAGE_LENGTH, shared_key); + sendnodes_ipv6(dht, source, packet + 1, plain, plain + CLIENT_ID_SIZE, sendback_data_length, shared_key); add_to_ping(dht->ping, packet + 1, source); @@ -1144,7 +1155,14 @@ static int handle_sendnodes_core(void *object, IP_Port source, uint8_t *packet, if (!sent_getnode_to_node(dht, packet + 1, source, plain + 1 + data_size, &sendback_node)) return 1; - int num_nodes = unpack_nodes(plain_nodes, plain[0], plain + 1, data_size); + uint16_t length_nodes = 0; + int num_nodes = unpack_nodes(plain_nodes, plain[0], &length_nodes, plain + 1, data_size); + + if (length_nodes != data_size) + return 1; + + if (num_nodes != plain[0]) + return 1; if (num_nodes <= 0) return 1; @@ -2030,7 +2048,7 @@ static int handle_hardening(void *object, IP_Port source, uint8_t *source_pubkey uint16_t length_nodes = length - 1 - CLIENT_ID_SIZE; Node_format nodes[MAX_SENT_NODES]; - int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, packet + 1 + CLIENT_ID_SIZE, length_nodes); + int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, 0, packet + 1 + CLIENT_ID_SIZE, length_nodes); /* TODO: MAX_SENT_NODES nodes should be returned at all times (right now we have a small network size so it could cause problems for testing and etc..) */ diff --git a/toxcore/DHT.h b/toxcore/DHT.h index c0731a3a..384a8450 100644 --- a/toxcore/DHT.h +++ b/toxcore/DHT.h @@ -144,12 +144,14 @@ Node_format; */ int pack_nodes(uint8_t *data, uint16_t length, Node_format *nodes, uint16_t number); -/* Unpack data of length into nodes of size (in number of nodes). +/* Unpack data of length into nodes of size max_num_nodes. + * Put the length of the data processed in processed_data_len. * * return number of unpacked nodes on success. * return -1 on failure. */ -int unpack_nodes(Node_format *nodes, uint16_t size, uint8_t *data, uint16_t length); +int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint16_t *processed_data_len, uint8_t *data, + uint16_t length); /*----------------------------------------------------------------------------------*/ diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index ee902d99..c7ebcd15 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c @@ -409,7 +409,7 @@ static int handle_announce_response(void *object, IP_Port source, uint8_t *packe if (len_nodes != 0) { Node_format nodes[MAX_SENT_NODES]; - int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, plain + 1 + ONION_PING_ID_SIZE, len_nodes); + int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, 0, plain + 1 + ONION_PING_ID_SIZE, len_nodes); if (num_nodes <= 0) return 1; @@ -500,7 +500,8 @@ static int handle_fakeid_announce(void *object, uint8_t *source_pubkey, uint8_t if (len_nodes != 0) { Node_format nodes[MAX_SENT_NODES]; - int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, data + 1 + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES, len_nodes); + int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, 0, data + 1 + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES, + len_nodes); if (num_nodes <= 0) return 1; From c16928c4aa606291eb05a94b8228096d3a71d11c Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 25 Apr 2014 09:15:53 -0400 Subject: [PATCH 032/117] MAX_SENT_NODE is now 4. This means that in every part of the Tox code that sends nodes will now send a maximum of 4 nodes instead of 8. --- toxcore/DHT.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toxcore/DHT.h b/toxcore/DHT.h index 384a8450..c37511a1 100644 --- a/toxcore/DHT.h +++ b/toxcore/DHT.h @@ -36,7 +36,7 @@ #define LCLIENT_LIST 32 /* The max number of nodes to send with send nodes. */ -#define MAX_SENT_NODES 8 +#define MAX_SENT_NODES 4 /* Ping timeout in seconds */ #define PING_TIMEOUT 3 From 45d122e2cbdd0a69dbd76941dc8a8a44ec1f0842 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 25 Apr 2014 11:17:20 -0400 Subject: [PATCH 033/117] Fixed building with NaCl. --- auto_tests/Makefile.inc | 1 + toxav/Makefile.inc | 1 + 2 files changed, 2 insertions(+) diff --git a/auto_tests/Makefile.inc b/auto_tests/Makefile.inc index a8771695..eaea8ac3 100644 --- a/auto_tests/Makefile.inc +++ b/auto_tests/Makefile.inc @@ -14,6 +14,7 @@ AUTOTEST_LDADD = \ $(NACL_LDFLAGS) \ libtoxcore.la \ $(LIBSODIUM_LIBS) \ + $(NACL_OBJECTS) \ $(NACL_LIBS) \ $(CHECK_LIBS) diff --git a/toxav/Makefile.inc b/toxav/Makefile.inc index 0cad1840..c3ab0da2 100644 --- a/toxav/Makefile.inc +++ b/toxav/Makefile.inc @@ -68,6 +68,7 @@ phone_LDADD = libtoxav.la \ $(OPUS_LIBS) \ $(VPX_LIBS)\ $(PTHREAD_LIBS)\ + $(NACL_OBJECTS) \ $(NACL_LIBS) From 09aa97f712f6988ba6cdb041a4708045a574b03b Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 25 Apr 2014 17:31:04 -0400 Subject: [PATCH 034/117] Fixed issue. --- toxcore/network.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toxcore/network.c b/toxcore/network.c index 7813ab03..6a7661c4 100644 --- a/toxcore/network.c +++ b/toxcore/network.c @@ -172,7 +172,7 @@ int set_socket_nosigpipe(sock_t sock) */ int set_socket_dualstack(sock_t sock) { - char ipv6only = 0; + int ipv6only = 0; socklen_t optsize = sizeof(ipv6only); int res = getsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6only, &optsize); From 82873d62c128cb04b4c89fd042042cb7b923e230 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 26 Apr 2014 12:30:29 -0400 Subject: [PATCH 035/117] Fixed minor issue. Socket used to find the broadcast ip was not closed when there was more than 16 broadcast interfaces. --- toxcore/LAN_discovery.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/toxcore/LAN_discovery.c b/toxcore/LAN_discovery.c index bed14754..9d1f055e 100644 --- a/toxcore/LAN_discovery.c +++ b/toxcore/LAN_discovery.c @@ -78,8 +78,10 @@ static void fetch_broadcast_info(uint16_t port) struct sockaddr_in *sock4 = (struct sockaddr_in *)&i_faces[i].ifr_broadaddr; - if (broadcast_count >= MAX_INTERFACES) + if (broadcast_count >= MAX_INTERFACES) { + close(sock); return; + } IP_Port *ip_port = &broadcast_ip_port[broadcast_count]; ip_port->ip.family = AF_INET; From 50cea69f5705a7a01e31417bae29feb920bfdd59 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sun, 27 Apr 2014 20:37:59 -0400 Subject: [PATCH 036/117] Added raw UDP cookie request packet handler. --- toxcore/net_crypto.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 2136e09f..3d36e8e0 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -46,9 +46,6 @@ static uint8_t crypt_connection_id_not_valid(Net_Crypto *c, int crypt_connection */ static int create_cookie_request(Net_Crypto *c, uint8_t *packet, uint8_t *dht_public_key, uint8_t *real_public_key) { - if (!c->dht) - return -1; - uint8_t plain[COOKIE_REQUEST_PLAIN_LENGTH]; memcpy(plain, c->self_public_key, crypto_box_PUBLICKEYBYTES); @@ -123,7 +120,7 @@ static int open_cookie(uint8_t *bytes, uint8_t *cookie, uint8_t *encryption_key) } -/* Create a cookie request packet and put it in packet. +/* Create a cookie response packet and put it in packet. * request_plain must be COOKIE_REQUEST_PLAIN_LENGTH bytes. * packet must be of size COOKIE_RESPONSE_LENGTH or bigger. * @@ -157,9 +154,6 @@ static int create_cookie_response(Net_Crypto *c, uint8_t *packet, uint8_t *reque static int handle_cookie_request(Net_Crypto *c, uint8_t *request_plain, uint8_t *shared_key, uint8_t *packet, uint16_t length) { - if (!c->dht) - return -1; - if (length != COOKIE_REQUEST_LENGTH) return -1; @@ -174,6 +168,28 @@ static int handle_cookie_request(Net_Crypto *c, uint8_t *request_plain, uint8_t return 0; } +/* Handle the cookie request packet (for raw UDP) + */ +static int udp_handle_cookie_request(void *object, IP_Port source, uint8_t *packet, uint32_t length) +{ + Net_Crypto *c = c; + uint8_t request_plain[COOKIE_REQUEST_PLAIN_LENGTH]; + uint8_t shared_key[crypto_box_BEFORENMBYTES]; + + if (handle_cookie_request(c, request_plain, shared_key, packet, length) != 0) + return 1; + + uint8_t data[COOKIE_RESPONSE_LENGTH]; + + if (create_cookie_response(c, data, request_plain, shared_key) != sizeof(data)) + return 1; + + if ((uint32_t)sendpacket(c->dht->net, source, data, sizeof(data)) != sizeof(data)) + return 1; + + return 0; +} + /* return 0 if there is no received data in the buffer. * return -1 if the packet was discarded. * return length of received data if successful. @@ -689,6 +705,8 @@ Net_Crypto *new_net_crypto(DHT *dht) new_keys(temp); new_symmetric_key(temp->secret_symmetric_key); + + networking_registerhandler(dht->net, NET_PACKET_COOKIE_REQUEST, &udp_handle_cookie_request, temp); return temp; } From b9370d519ff87020cf32f3d04b6a2c4eebcc9563 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Mon, 28 Apr 2014 20:14:07 -0400 Subject: [PATCH 037/117] Added some functions to create/handle middle level protocol packets. --- docs/Tox_middle_level_network_protocol.txt | 27 ++++- toxcore/crypto_core.c | 13 +++ toxcore/crypto_core.h | 4 + toxcore/net_crypto.c | 123 ++++++++++++++++++++- 4 files changed, 161 insertions(+), 6 deletions(-) diff --git a/docs/Tox_middle_level_network_protocol.txt b/docs/Tox_middle_level_network_protocol.txt index be8253cd..49ad330c 100644 --- a/docs/Tox_middle_level_network_protocol.txt +++ b/docs/Tox_middle_level_network_protocol.txt @@ -42,13 +42,13 @@ cookie request packet: [uint8_t 24][Senders DHT Public key (32 bytes)][Random nonce (24 bytes)][Encrypted message containing: [Senders real public key (32 bytes)][Recievers real public key (32 bytes)]] -Encrypted message is encrypted with sender DHT private key, recievers DHT public -key and the nonce. +Encrypted message is encrypted with sender DHT private key, recievers DHT +public key and the nonce. cookie response packet: [uint8_t 25][Random nonce (24 bytes)][Encrypted message containing: [Cookie]] -Encrypted message is encrypted with sender DHT private key, recievers DHT public -key and the nonce. +Encrypted message is encrypted with sender DHT private key, recievers DHT +public key and the nonce. The Cookie should be basically: [nonce][encrypted data:[uint64_t time][Senders real public key (32 @@ -61,3 +61,22 @@ nonce][session public key of the peer (32 bytes)]] The handshake packet is encrypted using the real private key of the sender, the real private key of the reciever and the nonce. + +Alice wants to connect to bob. + +Alice sends a cookie request packet to bob and gets a cookie response back. + +Alice then generates a nonce and a temporary public/private keypair. + +Alice then takes that nonce and just generated private key and the obtained +cookie and puts them in a handshake packet which she sends to bob. + +Bob gets the handshake packet, accepts the connection request, then generates a +nonce and a temporary public/private keypair and sends a handshake packet back +with this just generated information and with the cookie field being random +data/zeros. + +Both then use these temporary keys to generate the session key with which every +data packet sent and recieved will be encrypted and decrypted. The nonce sent +in the handshake will be used to encrypt the first data packet sent, the nonce ++ 1 the second, the nonce + 2 the third and so on. diff --git a/toxcore/crypto_core.c b/toxcore/crypto_core.c index 59053bc4..6e8b747a 100644 --- a/toxcore/crypto_core.c +++ b/toxcore/crypto_core.c @@ -42,6 +42,19 @@ uint8_t crypto_iszero(uint8_t *mem, uint32_t length) return check; // We return zero if mem is made out of zeroes. } +/* Use this instead of memcmp; not vulnerable to timing attacks. + returns 0 if both mem locations of length are equal. */ +unsigned int crypto_cmp(uint8_t *mem1, uint8_t *mem2, uint32_t length) +{ + unsigned int i, check = 0;; + + for (i = 0; i < length; ++i) { + check |= mem1[i] ^ mem2[i]; + } + + return check; +} + /* Precomputes the shared key from their public_key and our secret_key. * This way we can avoid an expensive elliptic curve scalar multiply for each * encrypt/decrypt operation. diff --git a/toxcore/crypto_core.h b/toxcore/crypto_core.h index a862635e..de8656c7 100644 --- a/toxcore/crypto_core.h +++ b/toxcore/crypto_core.h @@ -29,6 +29,10 @@ /* return zero if the buffer contains only zeros. */ uint8_t crypto_iszero(uint8_t *buffer, uint32_t blen); +/* Use this instead of memcmp; not vulnerable to timing attacks. + returns 0 if both mem locations of length are equal. */ +unsigned int crypto_cmp(uint8_t *mem1, uint8_t *mem2, uint32_t length); + /* Encrypts plain of length length to encrypted of length + 16 using the * public key(32 bytes) of the receiver and the secret key of the sender and a 24 byte nonce. * diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 3d36e8e0..97533512 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -94,7 +94,7 @@ static int create_cookie(uint8_t *cookie, uint8_t *bytes, uint8_t *encryption_ke #define COOKIE_RESPONSE_LENGTH (1 + crypto_box_NONCEBYTES + COOKIE_LENGTH + crypto_box_MACBYTES) -/* Open cookie of length COOKIE_LENGTH from bytes of length COOKIE_REQUEST_PLAIN_LENGTH using encryption_key +/* Open cookie of length COOKIE_LENGTH to bytes of length COOKIE_REQUEST_PLAIN_LENGTH using encryption_key * * return -1 on failure. * return 0 on success. @@ -172,7 +172,7 @@ static int handle_cookie_request(Net_Crypto *c, uint8_t *request_plain, uint8_t */ static int udp_handle_cookie_request(void *object, IP_Port source, uint8_t *packet, uint32_t length) { - Net_Crypto *c = c; + Net_Crypto *c = object; uint8_t request_plain[COOKIE_REQUEST_PLAIN_LENGTH]; uint8_t shared_key[crypto_box_BEFORENMBYTES]; @@ -190,6 +190,125 @@ static int udp_handle_cookie_request(void *object, IP_Port source, uint8_t *pack return 0; } +/* Handle a cookie response packet of length encrypted with shared_key. + * put the cookie in the response in cookie + * + * cookie must be of length COOKIE_LENGTH. + * + * return -1 on failure. + * return COOKIE_LENGTH on success. + */ +static int handle_cookie_response(Net_Crypto *c, uint8_t *cookie, uint8_t *packet, uint32_t length, uint8_t *shared_key) +{ + if (length != COOKIE_RESPONSE_LENGTH) + return -1; + + int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES, + length - (1 + crypto_box_NONCEBYTES), cookie); + + if (len != COOKIE_LENGTH) + return -1; + + return COOKIE_LENGTH; +} + +#define HANDSHAKE_PACKET_LENGTH (1 + COOKIE_LENGTH + crypto_box_NONCEBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES) + +/* Create a handshake packet and put it in packet. + * cookie must be COOKIE_LENGTH bytes. + * packet must be of size HANDSHAKE_PACKET_LENGTH or bigger. + * + * return -1 on failure. + * return HANDSHAKE_PACKET_LENGTH on success. + */ +static int create_crypto_handshake(Net_Crypto *c, uint8_t *packet, uint8_t *cookie, uint8_t *nonce, uint8_t *session_pk, + uint8_t *peer_real_pk) +{ + uint8_t plain[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES]; + memcpy(plain, nonce, crypto_box_NONCEBYTES); + memcpy(plain + crypto_box_NONCEBYTES, session_pk, crypto_box_PUBLICKEYBYTES); + new_nonce(packet + 1 + COOKIE_LENGTH); + int len = encrypt_data(peer_real_pk, c->self_secret_key, packet + 1 + COOKIE_LENGTH, plain, sizeof(plain), + packet + 1 + COOKIE_LENGTH + crypto_box_NONCEBYTES); + + if (len != HANDSHAKE_PACKET_LENGTH - (1 + COOKIE_LENGTH + crypto_box_NONCEBYTES)) + return -1; + + packet[0] = NET_PACKET_CRYPTO_HS; + memcpy(packet + 1, cookie, COOKIE_LENGTH); + + return HANDSHAKE_PACKET_LENGTH; +} + +/* Handle a crypto handshake packet of length. + * put the nonce contained in the packet in nonce, + * the session public key in session_pk and + * the real public key of the peer in peer_real_pk. + * + * nonce must be at least crypto_box_NONCEBYTES + * session_pk must be at least crypto_box_PUBLICKEYBYTES + * peer_real_pk must be at least crypto_box_PUBLICKEYBYTES + * + * return -1 on failure. + * return 0 on success. + */ +static int handle_crypto_handshake(Net_Crypto *c, uint8_t *nonce, uint8_t *session_pk, uint8_t *peer_real_pk, + uint8_t *packet, uint32_t length) +{ + if (length != HANDSHAKE_PACKET_LENGTH) + return -1; + + uint8_t cookie_plain[COOKIE_REQUEST_PLAIN_LENGTH]; + + if (open_cookie(cookie_plain, packet + 1, c->secret_symmetric_key) != 0) + return -1; + + if (crypto_cmp(cookie_plain + crypto_box_PUBLICKEYBYTES, c->self_public_key, crypto_box_PUBLICKEYBYTES) != 0) + return -1; + + uint8_t plain[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES]; + int len = decrypt_data(cookie_plain, c->self_secret_key, packet + 1 + COOKIE_LENGTH, + packet + 1 + COOKIE_LENGTH + crypto_box_NONCEBYTES, + HANDSHAKE_PACKET_LENGTH - (1 + COOKIE_LENGTH + crypto_box_NONCEBYTES), plain); + + if (len != sizeof(plain)) + return -1; + + memcpy(nonce, plain, crypto_box_NONCEBYTES); + memcpy(session_pk, plain + crypto_box_NONCEBYTES, crypto_box_PUBLICKEYBYTES); + memcpy(peer_real_pk, cookie_plain, crypto_box_PUBLICKEYBYTES); + return 0; +} + +/* Handle a crypto handshake packet of length without opening the cookie from peer + * with the real public key peer_real_pk. + * put the nonce contained in the packet in nonce and the session public key in + * session_pk. + * + * nonce must be at least crypto_box_NONCEBYTES + * session_pk must be at least crypto_box_PUBLICKEYBYTES + * + * return -1 on failure. + * return 0 on success. + */ +static int handle_crypto_handshake_nocookie(Net_Crypto *c, uint8_t *nonce, uint8_t *session_pk, uint8_t *packet, + uint32_t length, uint8_t *peer_real_pk) +{ + if (length != HANDSHAKE_PACKET_LENGTH) + return -1; + + uint8_t plain[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES]; + int len = decrypt_data(peer_real_pk, c->self_secret_key, packet + 1 + COOKIE_LENGTH, + packet + 1 + COOKIE_LENGTH + crypto_box_NONCEBYTES, + HANDSHAKE_PACKET_LENGTH - (1 + COOKIE_LENGTH + crypto_box_NONCEBYTES), plain); + + if (len != sizeof(plain)) + return -1; + + memcpy(nonce, plain, crypto_box_NONCEBYTES); + memcpy(session_pk, plain + crypto_box_NONCEBYTES, crypto_box_PUBLICKEYBYTES); + return 0; +} /* return 0 if there is no received data in the buffer. * return -1 if the packet was discarded. * return length of received data if successful. From 94545c3b50c6f87af702692ba171cacc577c669a Mon Sep 17 00:00:00 2001 From: irungentoo Date: Mon, 28 Apr 2014 20:27:23 -0400 Subject: [PATCH 038/117] Added some packet defines. --- toxcore/network.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/toxcore/network.h b/toxcore/network.h index 0e79954f..17b18a65 100644 --- a/toxcore/network.h +++ b/toxcore/network.h @@ -128,6 +128,8 @@ typedef int sock_t; #define NET_PACKET_DATA 18 /* Data packet ID. */ #define NET_PACKET_COOKIE_REQUEST 24 /* Cookie request packet */ #define NET_PACKET_COOKIE_RESPONSE 25 /* Cookie response packet */ +#define NET_PACKET_CRYPTO_HS 26 /* Crypto handshake packet */ +#define NET_PACKET_CRYPTO_DATA 27 /* Crypto data packet */ #define NET_PACKET_CRYPTO 32 /* Encrypted data packet ID. */ #define NET_PACKET_LAN_DISCOVERY 33 /* LAN discovery packet ID. */ #define NET_PACKET_GROUP_CHATS 48 /* Group chats packet ID. */ From 3863e01e2207198c20bf278c107f24a8cfbf1a73 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 29 Apr 2014 20:45:32 -0400 Subject: [PATCH 039/117] Some more work done on the middle network protocol. Handshake most likely has no more possible flaws to it, next thing to do is to do the same with the data packets. Wrote a couple more functions. --- docs/Tox_middle_level_network_protocol.txt | 17 +- toxcore/crypto_core.h | 2 +- toxcore/net_crypto.c | 233 +++++++++++++++++++-- toxcore/net_crypto.h | 36 +++- toxcore/network.h | 3 +- 5 files changed, 251 insertions(+), 40 deletions(-) diff --git a/docs/Tox_middle_level_network_protocol.txt b/docs/Tox_middle_level_network_protocol.txt index 49ad330c..39b275d2 100644 --- a/docs/Tox_middle_level_network_protocol.txt +++ b/docs/Tox_middle_level_network_protocol.txt @@ -56,10 +56,12 @@ bytes)][Recievers real public key (32 bytes)]] Handshake packet: [uint8_t 26][Cookie][nonce][Encrypted message containing: [random 24 bytes base -nonce][session public key of the peer (32 bytes)]] +nonce][session public key of the peer (32 bytes)][sha512 hash of the entire +Cookie sitting outside the encrypted part][Other Cookie (used by the other to +respond to the handshake packet)]] The handshake packet is encrypted using the real private key of the sender, the -real private key of the reciever and the nonce. +real private key of the receiver and the nonce. Alice wants to connect to bob. @@ -68,15 +70,16 @@ Alice sends a cookie request packet to bob and gets a cookie response back. Alice then generates a nonce and a temporary public/private keypair. -Alice then takes that nonce and just generated private key and the obtained -cookie and puts them in a handshake packet which she sends to bob. +Alice then takes that nonce and just generated private key, the obtained +cookie, creates a new cookie and puts them in a handshake packet which she +sends to bob. Bob gets the handshake packet, accepts the connection request, then generates a nonce and a temporary public/private keypair and sends a handshake packet back -with this just generated information and with the cookie field being random -data/zeros. +with this just generated information and with the cookie field being the Other +Cookie contained in the received handshake. Both then use these temporary keys to generate the session key with which every -data packet sent and recieved will be encrypted and decrypted. The nonce sent +data packet sent and received will be encrypted and decrypted. The nonce sent in the handshake will be used to encrypt the first data packet sent, the nonce + 1 the second, the nonce + 2 the third and so on. diff --git a/toxcore/crypto_core.h b/toxcore/crypto_core.h index de8656c7..1fca8078 100644 --- a/toxcore/crypto_core.h +++ b/toxcore/crypto_core.h @@ -29,7 +29,7 @@ /* return zero if the buffer contains only zeros. */ uint8_t crypto_iszero(uint8_t *buffer, uint32_t blen); -/* Use this instead of memcmp; not vulnerable to timing attacks. +/* Use this instead of memcmp; not vulnerable to timing attacks. returns 0 if both mem locations of length are equal. */ unsigned int crypto_cmp(uint8_t *mem1, uint8_t *mem2, uint32_t length); diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 97533512..81cff70a 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -212,7 +212,7 @@ static int handle_cookie_response(Net_Crypto *c, uint8_t *cookie, uint8_t *packe return COOKIE_LENGTH; } -#define HANDSHAKE_PACKET_LENGTH (1 + COOKIE_LENGTH + crypto_box_NONCEBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES) +#define HANDSHAKE_PACKET_LENGTH (1 + COOKIE_LENGTH + crypto_box_NONCEBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_hash_sha512_BYTES + COOKIE_LENGTH + crypto_box_MACBYTES) /* Create a handshake packet and put it in packet. * cookie must be COOKIE_LENGTH bytes. @@ -224,9 +224,18 @@ static int handle_cookie_response(Net_Crypto *c, uint8_t *cookie, uint8_t *packe static int create_crypto_handshake(Net_Crypto *c, uint8_t *packet, uint8_t *cookie, uint8_t *nonce, uint8_t *session_pk, uint8_t *peer_real_pk) { - uint8_t plain[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES]; + uint8_t plain[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_hash_sha512_BYTES + COOKIE_LENGTH]; memcpy(plain, nonce, crypto_box_NONCEBYTES); memcpy(plain + crypto_box_NONCEBYTES, session_pk, crypto_box_PUBLICKEYBYTES); + crypto_hash_sha512(plain + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, cookie, COOKIE_LENGTH); + uint8_t cookie_plain[COOKIE_REQUEST_PLAIN_LENGTH]; + memcpy(cookie_plain, peer_real_pk, crypto_box_PUBLICKEYBYTES); + memcpy(cookie_plain + crypto_box_PUBLICKEYBYTES, c->self_public_key, crypto_box_PUBLICKEYBYTES); + + if (create_cookie(plain + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_hash_sha512_BYTES, cookie_plain, + c->secret_symmetric_key) != 0) + return -1; + new_nonce(packet + 1 + COOKIE_LENGTH); int len = encrypt_data(peer_real_pk, c->self_secret_key, packet + 1 + COOKIE_LENGTH, plain, sizeof(plain), packet + 1 + COOKIE_LENGTH + crypto_box_NONCEBYTES); @@ -242,18 +251,23 @@ static int create_crypto_handshake(Net_Crypto *c, uint8_t *packet, uint8_t *cook /* Handle a crypto handshake packet of length. * put the nonce contained in the packet in nonce, - * the session public key in session_pk and - * the real public key of the peer in peer_real_pk. + * the session public key in session_pk + * the real public key of the peer in peer_real_pk and + * the cookie inside the encrypted part of the packet in cookie. + * + * if expected_real_pk isn't NULL it denotes the real public key + * the packet should be from. * * nonce must be at least crypto_box_NONCEBYTES * session_pk must be at least crypto_box_PUBLICKEYBYTES * peer_real_pk must be at least crypto_box_PUBLICKEYBYTES + * cookie must be at least COOKIE_LENGTH * * return -1 on failure. * return 0 on success. */ static int handle_crypto_handshake(Net_Crypto *c, uint8_t *nonce, uint8_t *session_pk, uint8_t *peer_real_pk, - uint8_t *packet, uint32_t length) + uint8_t *cookie, uint8_t *packet, uint32_t length, uint8_t *expected_real_pk) { if (length != HANDSHAKE_PACKET_LENGTH) return -1; @@ -263,10 +277,17 @@ static int handle_crypto_handshake(Net_Crypto *c, uint8_t *nonce, uint8_t *sessi if (open_cookie(cookie_plain, packet + 1, c->secret_symmetric_key) != 0) return -1; + if (expected_real_pk) + if (crypto_cmp(cookie_plain, expected_real_pk, crypto_box_PUBLICKEYBYTES) != 0) + return -1; + if (crypto_cmp(cookie_plain + crypto_box_PUBLICKEYBYTES, c->self_public_key, crypto_box_PUBLICKEYBYTES) != 0) return -1; - uint8_t plain[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES]; + uint8_t cookie_hash[crypto_hash_sha512_BYTES]; + crypto_hash_sha512(cookie_hash, packet + 1, COOKIE_LENGTH); + + uint8_t plain[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_hash_sha512_BYTES + COOKIE_LENGTH]; int len = decrypt_data(cookie_plain, c->self_secret_key, packet + 1 + COOKIE_LENGTH, packet + 1 + COOKIE_LENGTH + crypto_box_NONCEBYTES, HANDSHAKE_PACKET_LENGTH - (1 + COOKIE_LENGTH + crypto_box_NONCEBYTES), plain); @@ -274,40 +295,206 @@ static int handle_crypto_handshake(Net_Crypto *c, uint8_t *nonce, uint8_t *sessi if (len != sizeof(plain)) return -1; + if (memcmp(cookie_hash, plain + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, crypto_hash_sha512_BYTES) != 0) + return -1; + memcpy(nonce, plain, crypto_box_NONCEBYTES); memcpy(session_pk, plain + crypto_box_NONCEBYTES, crypto_box_PUBLICKEYBYTES); + memcpy(cookie, plain + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_hash_sha512_BYTES, COOKIE_LENGTH); memcpy(peer_real_pk, cookie_plain, crypto_box_PUBLICKEYBYTES); return 0; } -/* Handle a crypto handshake packet of length without opening the cookie from peer - * with the real public key peer_real_pk. - * put the nonce contained in the packet in nonce and the session public key in - * session_pk. - * - * nonce must be at least crypto_box_NONCEBYTES - * session_pk must be at least crypto_box_PUBLICKEYBYTES + +static Crypto_Connection *get_crypto_connection(Net_Crypto *c, int crypt_connection_id) +{ + if (crypt_connection_id_not_valid(c, crypt_connection_id)) + return 0; + + return &c->crypto_connections[crypt_connection_id]; +} + + +/* Sends a packet to the peer using the fastest route. * * return -1 on failure. * return 0 on success. */ -static int handle_crypto_handshake_nocookie(Net_Crypto *c, uint8_t *nonce, uint8_t *session_pk, uint8_t *packet, - uint32_t length, uint8_t *peer_real_pk) +static int send_packet_to(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint16_t length) { - if (length != HANDSHAKE_PACKET_LENGTH) +//TODO + + +} + +/* Add a new temp packet to send repeatedly. + * + * return -1 on failure. + * return 0 on success. + */ +static int new_temp_packet(Net_Crypto *c, int crypt_connection_id, uint8_t *packet, uint16_t length) +{ + if (length == 0 || length > MAX_CRYPTO_PACKET_SIZE) return -1; - uint8_t plain[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES]; - int len = decrypt_data(peer_real_pk, c->self_secret_key, packet + 1 + COOKIE_LENGTH, - packet + 1 + COOKIE_LENGTH + crypto_box_NONCEBYTES, - HANDSHAKE_PACKET_LENGTH - (1 + COOKIE_LENGTH + crypto_box_NONCEBYTES), plain); + Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); - if (len != sizeof(plain)) + if (conn == 0) return -1; - memcpy(nonce, plain, crypto_box_NONCEBYTES); - memcpy(session_pk, plain + crypto_box_NONCEBYTES, crypto_box_PUBLICKEYBYTES); + uint8_t *temp_packet = malloc(length); + + if (temp_packet == 0) + return -1; + + if (conn->temp_packet) + free(conn->temp_packet); + + memcpy(temp_packet, packet, length); + conn->temp_packet = temp_packet; + conn->temp_packet_length = length; + conn->temp_packet_sent_time = 0; return 0; +} + +/* Clear the temp packet. + * + * return -1 on failure. + * return 0 on success. + */ +static int clear_temp_packet(Net_Crypto *c, int crypt_connection_id) +{ + Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); + + if (conn == 0) + return -1; + + if (conn->temp_packet) + free(conn->temp_packet); + + conn->temp_packet = 0; + conn->temp_packet_length = 0; + conn->temp_packet_sent_time = 0; + return 0; +} + + +/* Send the temp packet. + * + * return -1 on failure. + * return 0 on success. + */ +static int send_temp_packet(Net_Crypto *c, int crypt_connection_id) +{ + Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); + + if (conn == 0) + return -1; + + if (!conn->temp_packet) + return -1; + + if (send_packet_to(c, crypt_connection_id, conn->temp_packet, conn->temp_packet_length) != 0) + return -1; + + conn->temp_packet_sent_time = current_time(); + return 0; +} + +/* Handle a packet that was recieved for the connection. + * + * return -1 on failure. + * return 0 on success. + */ +static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, uint8_t *packet, uint16_t length) +{ + if (length == 0 || length > MAX_CRYPTO_PACKET_SIZE) + return -1; + + Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); + + if (conn == 0) + return -1; + + switch (packet[0]) { + case NET_PACKET_COOKIE_RESPONSE: { + if (conn->status != CRYPTO_CONN_COOKIE_REQUESTED) + return -1; + + uint8_t cookie[COOKIE_LENGTH]; + + if (handle_cookie_response(c, cookie, packet, length, conn->shared_key) != sizeof(cookie)) + return -1; + + uint8_t handshake_packet[HANDSHAKE_PACKET_LENGTH]; + + if (create_crypto_handshake(c, handshake_packet, cookie, conn->sent_nonce, conn->sessionpublic_key, + conn->public_key) != sizeof(handshake_packet)) + return -1; + + if (new_temp_packet(c, crypt_connection_id, handshake_packet, sizeof(handshake_packet)) != 0) + return -1; + + send_temp_packet(c, crypt_connection_id); + conn->status = CRYPTO_CONN_HANDSHAKE_SENT; + return 0; + } + + case NET_PACKET_CRYPTO_HS: { + if (conn->status == CRYPTO_CONN_COOKIE_REQUESTED || conn->status == CRYPTO_CONN_HANDSHAKE_SENT) { + uint8_t peer_real_pk[crypto_box_PUBLICKEYBYTES]; + uint8_t cookie[COOKIE_LENGTH]; + + if (handle_crypto_handshake(c, conn->recv_nonce, conn->peersessionpublic_key, peer_real_pk, cookie, packet, length, + conn->public_key) != 0) + return -1; + + encrypt_precompute(conn->peersessionpublic_key, conn->sessionsecret_key, conn->shared_key); + + conn->status = CRYPTO_CONN_NOT_CONFIRMED; + } else { + return -1; + } + + return 0; + } + + case NET_PACKET_CRYPTO_DATA: { + if (conn->status == CRYPTO_CONN_NOT_CONFIRMED || conn->status == CRYPTO_CONN_ESTABLISHED) { + //TODO + } else { + return -1; + } + + return 0; + } + + default: { + return -1; + } + } + + return 0; +} + + +void new_connection_handler(Net_Crypto *c, int (*new_connection_callback)(void *object, New_Connection *n_c), + void *object) +{ + c->new_connection_callback = new_connection_callback; + c->new_connection_callback_object = object; +} + +static int handle_new_connection_handshake(Net_Crypto *c, uint8_t *data, uint16_t length) +{ + + +} + +int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c) +{ + + } /* return 0 if there is no received data in the buffer. * return -1 if the packet was discarded. diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index b2b9f4f5..85aeede6 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -30,10 +30,15 @@ #define CRYPTO_HANDSHAKE_TIMEOUT (CONNECTION_TIMEOUT * 2) #define CRYPTO_CONN_NO_CONNECTION 0 -#define CRYPTO_CONN_HANDSHAKE_SENT 1 -#define CRYPTO_CONN_NOT_CONFIRMED 2 -#define CRYPTO_CONN_ESTABLISHED 3 -#define CRYPTO_CONN_TIMED_OUT 4 +#define CRYPTO_CONN_COOKIE_REQUESTED 1 //send cookie request packets +#define CRYPTO_CONN_HANDSHAKE_SENT 2 //send handshake packets +#define CRYPTO_CONN_NOT_CONFIRMED 3 //send handshake packets +#define CRYPTO_CONN_ESTABLISHED 4 +#define CRYPTO_CONN_TIMED_OUT 5 + +#define CRYPTO_PACKET_BUFFER_SIZE 64 + +#define MAX_CRYPTO_PACKET_SIZE 1400 typedef struct { uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* The real public key of the peer. */ @@ -43,15 +48,27 @@ typedef struct { uint8_t sessionsecret_key[crypto_box_SECRETKEYBYTES]; /* Our private key for this session. */ uint8_t peersessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* The public key of the peer. */ uint8_t shared_key[crypto_box_BEFORENMBYTES]; /* The precomputed shared key from encrypt_precompute. */ - uint8_t status; /* 0 if no connection, 1 we have sent a handshake, 2 if connection is not confirmed yet - * (we have received a handshake but no empty data packet), 3 if the connection is established. - * 4 if the connection is timed out. + uint8_t status; /* 0 if no connection, 1 we are sending cookie request packets, + * 2 if we are sending handshake packets + * 3 if connection is not confirmed yet (we have received a handshake but no data packets yet), + * 4 if the connection is established. + * 5 if the connection is timed out. */ uint16_t number; /* Lossless_UDP connection number corresponding to this connection. */ uint64_t timeout; + uint8_t *temp_packet; /* Where the cookie request/handshake packet is stored while it is being sent. */ + uint16_t temp_packet_length; + uint64_t temp_packet_sent_time; /* The time at which the last temp_packet was sent in ms. */ } Crypto_Connection; +typedef struct { + uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* The real public key of the peer. */ + uint8_t recv_nonce[crypto_box_NONCEBYTES]; /* Nonce of received packets. */ + uint8_t peersessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* The public key of the peer. */ + uint8_t *cookie; + uint8_t cookie_length; +} New_Connection; typedef struct { Lossless_UDP *lossless_udp; @@ -67,9 +84,12 @@ typedef struct { /* The secret key used for cookies */ uint8_t secret_symmetric_key[crypto_box_KEYBYTES]; + + int (*new_connection_callback)(void *object, New_Connection *n_c); + void *new_connection_callback_object; } Net_Crypto; -#include "DHT.h" + /* return 0 if there is no received data in the buffer. * return -1 if the packet was discarded. diff --git a/toxcore/network.h b/toxcore/network.h index 17b18a65..21e225a0 100644 --- a/toxcore/network.h +++ b/toxcore/network.h @@ -104,6 +104,7 @@ typedef int sock_t; #include #include #include +#include #define crypto_box_MACBYTES (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES) #endif @@ -334,7 +335,7 @@ int set_socket_nosigpipe(sock_t sock); */ int set_socket_dualstack(sock_t sock); -/* return current time in milleseconds since the epoch. */ +/* return current UNIX time in microseconds (us). */ uint64_t current_time(void); /* return a random number. From 0505df009bc01ef7db6e31ee6ea999aaa83b8bfc Mon Sep 17 00:00:00 2001 From: irungentoo Date: Wed, 30 Apr 2014 09:24:05 -0400 Subject: [PATCH 040/117] Added number to cookie request/response packets to prevent possible DoS issue. --- docs/Tox_middle_level_network_protocol.txt | 6 ++- toxcore/net_crypto.c | 56 +++++++++++++--------- toxcore/net_crypto.h | 2 + 3 files changed, 40 insertions(+), 24 deletions(-) diff --git a/docs/Tox_middle_level_network_protocol.txt b/docs/Tox_middle_level_network_protocol.txt index 39b275d2..0382dd4e 100644 --- a/docs/Tox_middle_level_network_protocol.txt +++ b/docs/Tox_middle_level_network_protocol.txt @@ -41,12 +41,14 @@ Detailed implementation details: cookie request packet: [uint8_t 24][Senders DHT Public key (32 bytes)][Random nonce (24 bytes)][Encrypted message containing: [Senders real public key (32 -bytes)][Recievers real public key (32 bytes)]] +bytes)][Recievers real public key (32 bytes)][uint64_t number (must be sent back +untouched in cookie response)]] Encrypted message is encrypted with sender DHT private key, recievers DHT public key and the nonce. cookie response packet: -[uint8_t 25][Random nonce (24 bytes)][Encrypted message containing: [Cookie]] +[uint8_t 25][Random nonce (24 bytes)][Encrypted message containing: +[Cookie][uint64_t number (that was sent in the request)]] Encrypted message is encrypted with sender DHT private key, recievers DHT public key and the nonce. diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 81cff70a..71959c46 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -34,8 +34,16 @@ static uint8_t crypt_connection_id_not_valid(Net_Crypto *c, int crypt_connection { return (uint32_t)crypt_connection_id >= c->crypto_connections_length; } -#define COOKIE_REQUEST_PLAIN_LENGTH (crypto_box_PUBLICKEYBYTES * 2) + +/* cookie timeout in seconds */ +#define COOKIE_TIMEOUT 10 +#define COOKIE_DATA_LENGTH (crypto_box_PUBLICKEYBYTES * 2) +#define COOKIE_CONTENTS_LENGTH (sizeof(uint64_t) + COOKIE_DATA_LENGTH) +#define COOKIE_LENGTH (crypto_box_NONCEBYTES + COOKIE_CONTENTS_LENGTH + crypto_box_MACBYTES) + +#define COOKIE_REQUEST_PLAIN_LENGTH (COOKIE_DATA_LENGTH + sizeof(uint64_t)) #define COOKIE_REQUEST_LENGTH (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + COOKIE_REQUEST_PLAIN_LENGTH + crypto_box_MACBYTES) +#define COOKIE_RESPONSE_LENGTH (1 + crypto_box_NONCEBYTES + COOKIE_LENGTH + sizeof(uint64_t) + crypto_box_MACBYTES) /* Create a cookie request packet and put it in packet. * @@ -44,12 +52,14 @@ static uint8_t crypt_connection_id_not_valid(Net_Crypto *c, int crypt_connection * return -1 on failure. * return COOKIE_REQUEST_LENGTH on success. */ -static int create_cookie_request(Net_Crypto *c, uint8_t *packet, uint8_t *dht_public_key, uint8_t *real_public_key) +static int create_cookie_request(Net_Crypto *c, uint8_t *packet, uint8_t *dht_public_key, uint8_t *real_public_key, + uint64_t number) { uint8_t plain[COOKIE_REQUEST_PLAIN_LENGTH]; memcpy(plain, c->self_public_key, crypto_box_PUBLICKEYBYTES); memcpy(plain + crypto_box_PUBLICKEYBYTES, real_public_key, crypto_box_PUBLICKEYBYTES); + memcpy(plain + (crypto_box_PUBLICKEYBYTES * 2), &number, sizeof(uint64_t)); uint8_t shared_key[crypto_box_BEFORENMBYTES]; DHT_get_shared_key_sent(c->dht, shared_key, dht_public_key); @@ -67,12 +77,7 @@ static int create_cookie_request(Net_Crypto *c, uint8_t *packet, uint8_t *dht_pu return (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + len); } -/* cookie timeout in seconds */ -#define COOKIE_TIMEOUT 10 -#define COOKIE_CONTENTS_LENGTH (sizeof(uint64_t) + COOKIE_REQUEST_PLAIN_LENGTH) -#define COOKIE_LENGTH (crypto_box_NONCEBYTES + COOKIE_CONTENTS_LENGTH + crypto_box_MACBYTES) - -/* Create cookie of length COOKIE_LENGTH from bytes of length COOKIE_REQUEST_PLAIN_LENGTH using encryption_key +/* Create cookie of length COOKIE_LENGTH from bytes of length COOKIE_DATA_LENGTH using encryption_key * * return -1 on failure. * return 0 on success. @@ -82,7 +87,7 @@ static int create_cookie(uint8_t *cookie, uint8_t *bytes, uint8_t *encryption_ke uint8_t contents[COOKIE_CONTENTS_LENGTH]; uint64_t temp_time = unix_time(); memcpy(contents, &temp_time, sizeof(temp_time)); - memcpy(contents + sizeof(temp_time), bytes, COOKIE_REQUEST_PLAIN_LENGTH); + memcpy(contents + sizeof(temp_time), bytes, COOKIE_DATA_LENGTH); new_nonce(cookie); int len = encrypt_data_symmetric(encryption_key, cookie, contents, sizeof(contents), cookie + crypto_box_NONCEBYTES); @@ -92,9 +97,7 @@ static int create_cookie(uint8_t *cookie, uint8_t *bytes, uint8_t *encryption_ke return 0; } -#define COOKIE_RESPONSE_LENGTH (1 + crypto_box_NONCEBYTES + COOKIE_LENGTH + crypto_box_MACBYTES) - -/* Open cookie of length COOKIE_LENGTH to bytes of length COOKIE_REQUEST_PLAIN_LENGTH using encryption_key +/* Open cookie of length COOKIE_LENGTH to bytes of length COOKIE_DATA_LENGTH using encryption_key * * return -1 on failure. * return 0 on success. @@ -115,7 +118,7 @@ static int open_cookie(uint8_t *bytes, uint8_t *cookie, uint8_t *encryption_key) if (cookie_time + COOKIE_TIMEOUT < temp_time || temp_time < cookie_time) return -1; - memcpy(bytes, contents + sizeof(cookie_time), COOKIE_REQUEST_PLAIN_LENGTH); + memcpy(bytes, contents + sizeof(cookie_time), COOKIE_DATA_LENGTH); return 0; } @@ -129,14 +132,15 @@ static int open_cookie(uint8_t *bytes, uint8_t *cookie, uint8_t *encryption_key) */ static int create_cookie_response(Net_Crypto *c, uint8_t *packet, uint8_t *request_plain, uint8_t *shared_key) { - uint8_t cookie[COOKIE_LENGTH]; + uint8_t plain[COOKIE_LENGTH + sizeof(uint64_t)]; - if (create_cookie(cookie, request_plain, c->secret_symmetric_key) != 0) + if (create_cookie(plain, request_plain, c->secret_symmetric_key) != 0) return -1; + memcpy(plain + COOKIE_LENGTH, request_plain + COOKIE_DATA_LENGTH, sizeof(uint64_t)); packet[0] = NET_PACKET_COOKIE_RESPONSE; new_nonce(packet + 1); - int len = encrypt_data_symmetric(shared_key, packet + 1, cookie, sizeof(cookie), packet + 1 + crypto_box_NONCEBYTES); + int len = encrypt_data_symmetric(shared_key, packet + 1, plain, sizeof(plain), packet + 1 + crypto_box_NONCEBYTES); if (len != COOKIE_RESPONSE_LENGTH - (1 + crypto_box_NONCEBYTES)) return -1; @@ -198,17 +202,21 @@ static int udp_handle_cookie_request(void *object, IP_Port source, uint8_t *pack * return -1 on failure. * return COOKIE_LENGTH on success. */ -static int handle_cookie_response(Net_Crypto *c, uint8_t *cookie, uint8_t *packet, uint32_t length, uint8_t *shared_key) +static int handle_cookie_response(Net_Crypto *c, uint8_t *cookie, uint64_t *number, uint8_t *packet, uint32_t length, + uint8_t *shared_key) { if (length != COOKIE_RESPONSE_LENGTH) return -1; + uint8_t plain[COOKIE_LENGTH + sizeof(uint64_t)]; int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES, - length - (1 + crypto_box_NONCEBYTES), cookie); + length - (1 + crypto_box_NONCEBYTES), plain); - if (len != COOKIE_LENGTH) + if (len != sizeof(plain)) return -1; + memcpy(cookie, plain, COOKIE_LENGTH); + memcpy(number, plain + COOKIE_LENGTH, sizeof(uint64_t)); return COOKIE_LENGTH; } @@ -228,7 +236,7 @@ static int create_crypto_handshake(Net_Crypto *c, uint8_t *packet, uint8_t *cook memcpy(plain, nonce, crypto_box_NONCEBYTES); memcpy(plain + crypto_box_NONCEBYTES, session_pk, crypto_box_PUBLICKEYBYTES); crypto_hash_sha512(plain + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, cookie, COOKIE_LENGTH); - uint8_t cookie_plain[COOKIE_REQUEST_PLAIN_LENGTH]; + uint8_t cookie_plain[COOKIE_DATA_LENGTH]; memcpy(cookie_plain, peer_real_pk, crypto_box_PUBLICKEYBYTES); memcpy(cookie_plain + crypto_box_PUBLICKEYBYTES, c->self_public_key, crypto_box_PUBLICKEYBYTES); @@ -272,7 +280,7 @@ static int handle_crypto_handshake(Net_Crypto *c, uint8_t *nonce, uint8_t *sessi if (length != HANDSHAKE_PACKET_LENGTH) return -1; - uint8_t cookie_plain[COOKIE_REQUEST_PLAIN_LENGTH]; + uint8_t cookie_plain[COOKIE_DATA_LENGTH]; if (open_cookie(cookie_plain, packet + 1, c->secret_symmetric_key) != 0) return -1; @@ -422,8 +430,12 @@ static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, uint return -1; uint8_t cookie[COOKIE_LENGTH]; + uint64_t number; - if (handle_cookie_response(c, cookie, packet, length, conn->shared_key) != sizeof(cookie)) + if (handle_cookie_response(c, cookie, &number, packet, length, conn->shared_key) != sizeof(cookie)) + return -1; + + if (number != conn->cookie_request_number) return -1; uint8_t handshake_packet[HANDSHAKE_PACKET_LENGTH]; diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index 85aeede6..8dac937e 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -57,6 +57,8 @@ typedef struct { uint16_t number; /* Lossless_UDP connection number corresponding to this connection. */ uint64_t timeout; + uint64_t cookie_request_number; /* number used in the cookie request packets for this connection */ + uint8_t *temp_packet; /* Where the cookie request/handshake packet is stored while it is being sent. */ uint16_t temp_packet_length; uint64_t temp_packet_sent_time; /* The time at which the last temp_packet was sent in ms. */ From 5715e5016940abab7009f093a7c0785440dd2de8 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Wed, 30 Apr 2014 20:53:43 -0400 Subject: [PATCH 041/117] Some more code written for the middle level protocol stuff. --- toxcore/net_crypto.c | 216 ++++++++++++++++++++++++++++++++++++++++++- toxcore/net_crypto.h | 7 +- 2 files changed, 218 insertions(+), 5 deletions(-) diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 71959c46..3f74cf04 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -46,6 +46,8 @@ static uint8_t crypt_connection_id_not_valid(Net_Crypto *c, int crypt_connection #define COOKIE_RESPONSE_LENGTH (1 + crypto_box_NONCEBYTES + COOKIE_LENGTH + sizeof(uint64_t) + crypto_box_MACBYTES) /* Create a cookie request packet and put it in packet. + * dht_public_key is the dht public key of the other + * real_public_key is the real public key of the other. * * packet must be of size COOKIE_REQUEST_LENGTH or bigger. * @@ -426,7 +428,7 @@ static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, uint switch (packet[0]) { case NET_PACKET_COOKIE_RESPONSE: { - if (conn->status != CRYPTO_CONN_COOKIE_REQUESTED) + if (conn->status != CRYPTO_CONN_COOKIE_REQUESTING) return -1; uint8_t cookie[COOKIE_LENGTH]; @@ -453,7 +455,7 @@ static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, uint } case NET_PACKET_CRYPTO_HS: { - if (conn->status == CRYPTO_CONN_COOKIE_REQUESTED || conn->status == CRYPTO_CONN_HANDSHAKE_SENT) { + if (conn->status == CRYPTO_CONN_COOKIE_REQUESTING || conn->status == CRYPTO_CONN_HANDSHAKE_SENT) { uint8_t peer_real_pk[crypto_box_PUBLICKEYBYTES]; uint8_t cookie[COOKIE_LENGTH]; @@ -489,6 +491,95 @@ static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, uint return 0; } +/* Set the size of the friend list to numfriends. + * + * return -1 if realloc fails. + * return 0 if it succeeds. + */ +static int realloc_cryptoconnection(Net_Crypto *c, uint32_t num) +{ + if (num == 0) { + free(c->crypto_connections); + c->crypto_connections = NULL; + return 0; + } + + Crypto_Connection *newcrypto_connections = realloc(c->crypto_connections, num * sizeof(Crypto_Connection)); + + if (newcrypto_connections == NULL) + return -1; + + c->crypto_connections = newcrypto_connections; + return 0; +} + + +/* Create a new empty crypto connection. + * + * return -1 on failure. + * return connection id on success. + */ +static int create_crypto_connection(Net_Crypto *c) +{ + uint32_t i; + + for (i = 0; i <= c->crypto_connections_length; ++i) { + if (c->crypto_connections[i].status == CRYPTO_CONN_NO_CONNECTION) + return i; + } + + if (realloc_cryptoconnection(c, c->crypto_connections_length + 1) == -1) + return -1; + + memset(&(c->crypto_connections[c->crypto_connections_length]), 0, sizeof(Crypto_Connection)); + int id = c->crypto_connections_length; + ++c->crypto_connections_length; + return id; +} + +/* Wipe a crypto connection. + * + * return -1 on failure. + * return 0 on success. + */ +static int wipe_crypto_connection(Net_Crypto *c, int crypt_connection_id) +{ + if (crypt_connection_id_not_valid(c, crypt_connection_id)) + return -1; + + uint32_t i; + memset(&(c->crypto_connections[crypt_connection_id]), 0 , sizeof(Crypto_Connection)); + + for (i = c->crypto_connections_length; i != 0; --i) { + if (c->crypto_connections[i - 1].status != CRYPTO_CONN_NO_CONNECTION) + break; + } + + if (c->crypto_connections_length != i) { + c->crypto_connections_length = i; + realloc_cryptoconnection(c, c->crypto_connections_length); + } + + return 0; +} + +/* Get crypto connection id from public key of peer. + * + * return -1 if there are no connections like we are looking for. + * return id if it found it. + */ +static int getcryptconnection_id(Net_Crypto *c, uint8_t *public_key) +{ + uint32_t i; + + for (i = 0; i < c->crypto_connections_length; ++i) { + if (c->crypto_connections[i].status != CRYPTO_CONN_NO_CONNECTION) + if (memcmp(public_key, c->crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) + return i; + } + + return -1; +} void new_connection_handler(Net_Crypto *c, int (*new_connection_callback)(void *object, New_Connection *n_c), void *object) @@ -497,17 +588,136 @@ void new_connection_handler(Net_Crypto *c, int (*new_connection_callback)(void * c->new_connection_callback_object = object; } -static int handle_new_connection_handshake(Net_Crypto *c, uint8_t *data, uint16_t length) +/* Handle a handshake packet by someone who wants to initiate a new connection with us. + * This calls the callback set by new_connection_handler() if the handshake is ok. + * + * return -1 on failure. + * return 0 on success. + */ +static int handle_new_connection_handshake(Net_Crypto *c, IP_Port source, uint8_t *data, uint16_t length) { + New_Connection n_c; + n_c.cookie = malloc(COOKIE_LENGTH); + if (n_c.cookie == NULL) + return -1; + n_c.source = source; + n_c.cookie_length = COOKIE_LENGTH; + + if (handle_crypto_handshake(c, n_c.recv_nonce, n_c.peersessionpublic_key, n_c.public_key, n_c.cookie, data, length, + 0) != 0) + return -1; + + return c->new_connection_callback(c->new_connection_callback_object, &n_c); } +/* Accept a crypto connection. + * + * return -1 on failure. + * return connection id on success. + */ int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c) { + //TODO: do something with n_c->source. + if (getcryptconnection_id(c, n_c->public_key) != -1) + return -1; + int crypt_connection_id = create_crypto_connection(c); + if (crypt_connection_id == -1) + return -1; + + Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); + + if (conn == 0) + return -1; + + memcpy(conn->public_key, n_c->public_key, crypto_box_PUBLICKEYBYTES); + memcpy(conn->recv_nonce, n_c->recv_nonce, crypto_box_NONCEBYTES); + memcpy(conn->peersessionpublic_key, n_c->peersessionpublic_key, crypto_box_PUBLICKEYBYTES); + random_nonce(conn->sent_nonce); + crypto_box_keypair(conn->sessionpublic_key, conn->sessionsecret_key); + encrypt_precompute(conn->peersessionpublic_key, conn->sessionsecret_key, conn->shared_key); + + if (n_c->cookie_length != COOKIE_LENGTH) + return -1; + + uint8_t handshake_packet[HANDSHAKE_PACKET_LENGTH]; + + if (create_crypto_handshake(c, handshake_packet, n_c->cookie, conn->sent_nonce, conn->sessionpublic_key, + conn->public_key) != sizeof(handshake_packet)) + return -1; + + if (new_temp_packet(c, crypt_connection_id, handshake_packet, sizeof(handshake_packet)) != 0) + return -1; + + send_temp_packet(c, crypt_connection_id); + conn->status = CRYPTO_CONN_NOT_CONFIRMED; + return crypt_connection_id; } + +/* Create a crypto connection. + * If one to that real public key already exists, return it. + * + * return -1 on failure. + * return connection id on success. + */ +int new_crypto_connection(Net_Crypto *c, uint8_t *real_public_key) +{ + int crypt_connection_id = getcryptconnection_id(c, real_public_key); + + if (crypt_connection_id != -1) + return crypt_connection_id; + + crypt_connection_id = create_crypto_connection(c); + + if (crypt_connection_id == -1) + return -1; + + Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); + + if (conn == 0) + return -1; + + memcpy(conn->public_key, real_public_key, crypto_box_PUBLICKEYBYTES); + random_nonce(conn->sent_nonce); + crypto_box_keypair(conn->sessionpublic_key, conn->sessionsecret_key); + conn->status = CRYPTO_CONN_COOKIE_REQUESTING; + return crypt_connection_id; +} + +/* Set the DHT public key of the crypto connection. + * If one to that real public key already exists, return it. + * + * return -1 on failure. + * return 0 on success. + */ +int set_conection_dht_public_key(Net_Crypto *c, int crypt_connection_id, uint8_t *dht_public_key) +{ + Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); + + if (conn == 0) + return -1; + + memcpy(conn->dht_public_key, dht_public_key, crypto_box_PUBLICKEYBYTES); + conn->dht_public_key_set = 1; + + if (conn->status == CRYPTO_CONN_COOKIE_REQUESTING) { + conn->cookie_request_number = random_64b(); + uint8_t cookie_request[COOKIE_REQUEST_LENGTH]; + + if (create_cookie_request(c, cookie_request, conn->dht_public_key, conn->public_key, + conn->cookie_request_number) != sizeof(cookie_request)) + return -1; + + if (new_temp_packet(c, crypt_connection_id, cookie_request, sizeof(cookie_request)) != 0) + return -1; + }//TODO + + return 0; +} + /* return 0 if there is no received data in the buffer. * return -1 if the packet was discarded. * return length of received data if successful. diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index 8dac937e..0d27ae4d 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -30,7 +30,7 @@ #define CRYPTO_HANDSHAKE_TIMEOUT (CONNECTION_TIMEOUT * 2) #define CRYPTO_CONN_NO_CONNECTION 0 -#define CRYPTO_CONN_COOKIE_REQUESTED 1 //send cookie request packets +#define CRYPTO_CONN_COOKIE_REQUESTING 1 //send cookie request packets #define CRYPTO_CONN_HANDSHAKE_SENT 2 //send handshake packets #define CRYPTO_CONN_NOT_CONFIRMED 3 //send handshake packets #define CRYPTO_CONN_ESTABLISHED 4 @@ -39,7 +39,7 @@ #define CRYPTO_PACKET_BUFFER_SIZE 64 #define MAX_CRYPTO_PACKET_SIZE 1400 - +#define MAX_CRYPTO_DATA_SIZE (MAX_CRYPTO_PACKET_SIZE - (1 + sizeof(uint16_t) + crypto_box_MACBYTES)) typedef struct { uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* The real public key of the peer. */ uint8_t recv_nonce[crypto_box_NONCEBYTES]; /* Nonce of received packets. */ @@ -58,6 +58,8 @@ typedef struct { uint64_t timeout; uint64_t cookie_request_number; /* number used in the cookie request packets for this connection */ + uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; /* The dht public key of the peer */ + uint8_t dht_public_key_set; /* True if the dht public key is set, false if it isn't. */ uint8_t *temp_packet; /* Where the cookie request/handshake packet is stored while it is being sent. */ uint16_t temp_packet_length; @@ -65,6 +67,7 @@ typedef struct { } Crypto_Connection; typedef struct { + IP_Port source; uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* The real public key of the peer. */ uint8_t recv_nonce[crypto_box_NONCEBYTES]; /* Nonce of received packets. */ uint8_t peersessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* The public key of the peer. */ From 509edb983f384ea62191f1c68129b3942e55fa65 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Wed, 30 Apr 2014 21:01:09 -0400 Subject: [PATCH 042/117] Remove duplicates. --- toxcore/net_crypto.c | 39 --------------------------------------- 1 file changed, 39 deletions(-) diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 3f74cf04..3bc2ce33 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -856,45 +856,6 @@ static int handle_cryptohandshake(Net_Crypto *c, uint8_t *public_key, uint8_t *s return 1; } -/* Get crypto connection id from public key of peer. - * - * return -1 if there are no connections like we are looking for. - * return id if it found it. - */ -static int getcryptconnection_id(Net_Crypto *c, uint8_t *public_key) -{ - uint32_t i; - - for (i = 0; i < c->crypto_connections_length; ++i) { - if (c->crypto_connections[i].status != CRYPTO_CONN_NO_CONNECTION) - if (memcmp(public_key, c->crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) - return i; - } - - return -1; -} - -/* Set the size of the friend list to numfriends. - * - * return -1 if realloc fails. - * return 0 if it succeeds. - */ -static int realloc_cryptoconnection(Net_Crypto *c, uint32_t num) -{ - if (num == 0) { - free(c->crypto_connections); - c->crypto_connections = NULL; - return 0; - } - - Crypto_Connection *newcrypto_connections = realloc(c->crypto_connections, num * sizeof(Crypto_Connection)); - - if (newcrypto_connections == NULL) - return -1; - - c->crypto_connections = newcrypto_connections; - return 0; -} /* Start a secure connection with other peer who has public_key and ip_port. * From 19a4b1e443f015e38d04decbe8e042acb17d8ae8 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 1 May 2014 08:06:24 -0400 Subject: [PATCH 043/117] Improved the crypto_cmp function. It now uses the NaCl functions when the length is appropriate. Moved crypto defines to crypto_core.h --- toxcore/crypto_core.c | 25 ++++++++++--------------- toxcore/crypto_core.h | 18 +++++++++++++++--- toxcore/network.h | 13 ------------- 3 files changed, 25 insertions(+), 31 deletions(-) diff --git a/toxcore/crypto_core.c b/toxcore/crypto_core.c index 6e8b747a..3f3e7b48 100644 --- a/toxcore/crypto_core.c +++ b/toxcore/crypto_core.c @@ -29,30 +29,25 @@ #include "crypto_core.h" -/* Use this instead of memcmp; not vulnerable to timing attacks. */ -uint8_t crypto_iszero(uint8_t *mem, uint32_t length) -{ - uint8_t check = 0; - uint32_t i; - - for (i = 0; i < length; ++i) { - check |= mem[i]; - } - - return check; // We return zero if mem is made out of zeroes. -} /* Use this instead of memcmp; not vulnerable to timing attacks. - returns 0 if both mem locations of length are equal. */ + returns 0 if both mem locations of length are equal, + return -1 if they are not. */ unsigned int crypto_cmp(uint8_t *mem1, uint8_t *mem2, uint32_t length) { - unsigned int i, check = 0;; + if (length == 16) { + return crypto_verify_16(mem1, mem2); + } else if (length == 32) { + return crypto_verify_32(mem1, mem2); + } + + unsigned int i, check = 0; for (i = 0; i < length; ++i) { check |= mem1[i] ^ mem2[i]; } - return check; + return (1 & ((check - 1) >> 8)) - 1; } /* Precomputes the shared key from their public_key and our secret_key. diff --git a/toxcore/crypto_core.h b/toxcore/crypto_core.h index 1fca8078..7ee5f59e 100644 --- a/toxcore/crypto_core.h +++ b/toxcore/crypto_core.h @@ -25,12 +25,24 @@ #include "network.h" +#ifndef VANILLA_NACL +/* We use libsodium by default. */ +#include +#else +#include +#include +#include +#include +#include +#include +#define crypto_box_MACBYTES (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES) +#endif -/* return zero if the buffer contains only zeros. */ -uint8_t crypto_iszero(uint8_t *buffer, uint32_t blen); +#define crypto_box_KEYBYTES (crypto_box_BEFORENMBYTES) /* Use this instead of memcmp; not vulnerable to timing attacks. - returns 0 if both mem locations of length are equal. */ + returns 0 if both mem locations of length are equal, + return -1 if they are not. */ unsigned int crypto_cmp(uint8_t *mem1, uint8_t *mem2, uint32_t length); /* Encrypts plain of length length to encrypted of length + 16 using the diff --git a/toxcore/network.h b/toxcore/network.h index 21e225a0..d19f144c 100644 --- a/toxcore/network.h +++ b/toxcore/network.h @@ -97,19 +97,6 @@ typedef int sock_t; #endif #endif -#ifndef VANILLA_NACL -/* We use libsodium by default. */ -#include -#else -#include -#include -#include -#include -#define crypto_box_MACBYTES (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES) -#endif - -#define crypto_box_KEYBYTES (crypto_box_BEFORENMBYTES) - #ifndef IPV6_ADD_MEMBERSHIP #ifdef IPV6_JOIN_GROUP #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP From 47aa53a3840f81b42e0f78dea03a57ebd7c3ebb5 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 1 May 2014 19:20:28 -0400 Subject: [PATCH 044/117] Protocol implementation is starting to look ok. Still need to decide exactly how data packets will work though. --- auto_tests/crypto_test.c | 7 +- docs/Tox_middle_level_network_protocol.txt | 9 + toxcore/crypto_core.c | 2 +- toxcore/crypto_core.h | 2 +- toxcore/net_crypto.c | 267 ++++++++++++++++++++- toxcore/net_crypto.h | 8 + 6 files changed, 277 insertions(+), 18 deletions(-) diff --git a/auto_tests/crypto_test.c b/auto_tests/crypto_test.c index 917aa81d..39893515 100644 --- a/auto_tests/crypto_test.c +++ b/auto_tests/crypto_test.c @@ -9,12 +9,6 @@ #include #include #include -#ifndef VANILLA_NACL -#include -#else -#include -#define crypto_box_MACBYTES (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES) -#endif void rand_bytes(uint8_t *b, size_t blen) { @@ -276,6 +270,7 @@ START_TEST(test_large_data_symmetric) } END_TEST + #define DEFTESTCASE(NAME) \ TCase *NAME = tcase_create(#NAME); \ tcase_add_test(NAME, test_##NAME); \ diff --git a/docs/Tox_middle_level_network_protocol.txt b/docs/Tox_middle_level_network_protocol.txt index 0382dd4e..7b65db51 100644 --- a/docs/Tox_middle_level_network_protocol.txt +++ b/docs/Tox_middle_level_network_protocol.txt @@ -85,3 +85,12 @@ Both then use these temporary keys to generate the session key with which every data packet sent and received will be encrypted and decrypted. The nonce sent in the handshake will be used to encrypt the first data packet sent, the nonce + 1 the second, the nonce + 2 the third and so on. + +Data packets: + +[uint8_t 27][uint16_t (in network byte order) the last 2 bytes of the nonce used +to encrypt this][encrypted with the session key and a nonce:[data]] + +Data in the data packets: +... + diff --git a/toxcore/crypto_core.c b/toxcore/crypto_core.c index 3f3e7b48..0b1971e7 100644 --- a/toxcore/crypto_core.c +++ b/toxcore/crypto_core.c @@ -33,7 +33,7 @@ /* Use this instead of memcmp; not vulnerable to timing attacks. returns 0 if both mem locations of length are equal, return -1 if they are not. */ -unsigned int crypto_cmp(uint8_t *mem1, uint8_t *mem2, uint32_t length) +int crypto_cmp(uint8_t *mem1, uint8_t *mem2, uint32_t length) { if (length == 16) { return crypto_verify_16(mem1, mem2); diff --git a/toxcore/crypto_core.h b/toxcore/crypto_core.h index 7ee5f59e..c5969453 100644 --- a/toxcore/crypto_core.h +++ b/toxcore/crypto_core.h @@ -43,7 +43,7 @@ /* Use this instead of memcmp; not vulnerable to timing attacks. returns 0 if both mem locations of length are equal, return -1 if they are not. */ -unsigned int crypto_cmp(uint8_t *mem1, uint8_t *mem2, uint32_t length); +int crypto_cmp(uint8_t *mem1, uint8_t *mem2, uint32_t length); /* Encrypts plain of length length to encrypted of length + 16 using the * public key(32 bytes) of the receiver and the secret key of the sender and a 24 byte nonce. diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 3bc2ce33..ad41ce78 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -35,6 +35,21 @@ static uint8_t crypt_connection_id_not_valid(Net_Crypto *c, int crypt_connection return (uint32_t)crypt_connection_id >= c->crypto_connections_length; } +/* return 0 if connection is dead. + * return 1 if connection is alive. + */ +static int is_alive(uint8_t status) +{ + if (status == CRYPTO_CONN_COOKIE_REQUESTING || + status == CRYPTO_CONN_HANDSHAKE_SENT || + status == CRYPTO_CONN_NOT_CONFIRMED || + status == CRYPTO_CONN_ESTABLISHED) { + return 1; + } + + return 0; +} + /* cookie timeout in seconds */ #define COOKIE_TIMEOUT 10 #define COOKIE_DATA_LENGTH (crypto_box_PUBLICKEYBYTES * 2) @@ -55,7 +70,7 @@ static uint8_t crypt_connection_id_not_valid(Net_Crypto *c, int crypt_connection * return COOKIE_REQUEST_LENGTH on success. */ static int create_cookie_request(Net_Crypto *c, uint8_t *packet, uint8_t *dht_public_key, uint8_t *real_public_key, - uint64_t number) + uint64_t number, uint8_t *shared_key) { uint8_t plain[COOKIE_REQUEST_PLAIN_LENGTH]; @@ -63,7 +78,6 @@ static int create_cookie_request(Net_Crypto *c, uint8_t *packet, uint8_t *dht_pu memcpy(plain + crypto_box_PUBLICKEYBYTES, real_public_key, crypto_box_PUBLICKEYBYTES); memcpy(plain + (crypto_box_PUBLICKEYBYTES * 2), &number, sizeof(uint64_t)); - uint8_t shared_key[crypto_box_BEFORENMBYTES]; DHT_get_shared_key_sent(c->dht, shared_key, dht_public_key); uint8_t nonce[crypto_box_NONCEBYTES]; new_nonce(nonce); @@ -204,7 +218,7 @@ static int udp_handle_cookie_request(void *object, IP_Port source, uint8_t *pack * return -1 on failure. * return COOKIE_LENGTH on success. */ -static int handle_cookie_response(Net_Crypto *c, uint8_t *cookie, uint64_t *number, uint8_t *packet, uint32_t length, +static int handle_cookie_response(uint8_t *cookie, uint64_t *number, uint8_t *packet, uint32_t length, uint8_t *shared_key) { if (length != COOKIE_RESPONSE_LENGTH) @@ -332,9 +346,90 @@ static Crypto_Connection *get_crypto_connection(Net_Crypto *c, int crypt_connect */ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint16_t length) { -//TODO +//TODO TCP, etc... + Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); + if (conn == 0) + return -1; + if ((uint32_t)sendpacket(c->dht->net, conn->ip_port, data, length) != length) + return -1; + + return 0; +} + +#define MAX_DATA_DATA_PACKET_SIZE (MAX_CRYPTO_PACKET_SIZE - (1 + sizeof(uint16_t) + crypto_box_MACBYTES)) + +static int send_data_packet(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint16_t length) +{ + if (length == 0 || length + (1 + sizeof(uint16_t) + crypto_box_MACBYTES) > MAX_CRYPTO_PACKET_SIZE) + return -1; + + Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); + + if (conn == 0) + return -1; + + uint8_t packet[1 + sizeof(uint16_t) + length + crypto_box_MACBYTES]; + packet[0] = NET_PACKET_CRYPTO_DATA; + memcpy(packet + 1, conn->sent_nonce + (crypto_box_NONCEBYTES - sizeof(uint16_t)), sizeof(uint16_t)); + int len = encrypt_data_symmetric(conn->shared_key, conn->sent_nonce, data, length, packet + 1 + sizeof(uint16_t)); + + if (len + 1 + sizeof(uint16_t) != sizeof(packet)) + return -1; + + increment_nonce(conn->sent_nonce); + return send_packet_to(c, crypt_connection_id, packet, sizeof(packet)); +} + +/* Get the lowest 2 bytes from the nonce and convert + * them to host byte format before returning them. + */ +uint16_t get_nonce_uint16(uint8_t *nonce) +{ + uint16_t num; + memcpy(&num, nonce + (crypto_box_NONCEBYTES - sizeof(uint16_t)), sizeof(uint16_t)); + return ntohs(num); +} + +#define DATA_NUM_THRESHOLD 21845 + +/* Handle a data packet. + * Decrypt packet of length and put it into data. + * data must be at least MAX_DATA_DATA_PACKET_SIZE big. + * + * return -1 on failure. + * return length of data on success. + */ +static int handle_data_packet(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint8_t *packet, uint16_t length) +{ + if (length <= (1 + sizeof(uint16_t) + crypto_box_MACBYTES) || length > MAX_CRYPTO_PACKET_SIZE) + return -1; + + Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); + + if (conn == 0) + return -1; + + uint8_t nonce[crypto_box_NONCEBYTES]; + memcpy(nonce, conn->recv_nonce, crypto_box_NONCEBYTES); + uint16_t num_cur_nonce = get_nonce_uint16(nonce); + uint16_t num; + memcpy(&num, packet + 1, sizeof(uint16_t)); + num = ntohs(num); + uint16_t diff = num - num_cur_nonce; + increment_nonce_number(nonce, diff); + int len = decrypt_data_symmetric(conn->shared_key, nonce, packet + 1 + sizeof(uint16_t), + length - (1 + sizeof(uint16_t)), data); + + if ((unsigned int)len != length - (1 + sizeof(uint16_t) + crypto_box_MACBYTES)) + return -1; + + if (diff > DATA_NUM_THRESHOLD * 2) { + increment_nonce_number(conn->recv_nonce, DATA_NUM_THRESHOLD); + } + + return len; } /* Add a new temp packet to send repeatedly. @@ -434,7 +529,7 @@ static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, uint uint8_t cookie[COOKIE_LENGTH]; uint64_t number; - if (handle_cookie_response(c, cookie, &number, packet, length, conn->shared_key) != sizeof(cookie)) + if (handle_cookie_response(cookie, &number, packet, length, conn->shared_key) != sizeof(cookie)) return -1; if (number != conn->cookie_request_number) @@ -581,6 +676,37 @@ static int getcryptconnection_id(Net_Crypto *c, uint8_t *public_key) return -1; } +/* Add a source to the crypto connection. + * This is to be used only when we have recieved a packet from that source. + * + * return -1 on failure. + * return positive number on success. + * 0 if source was a direct UDP connection. + * TODO + */ +static int crypto_connection_add_source(Net_Crypto *c, int crypt_connection_id, IP_Port source) +{ + Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); + + if (conn == 0) + return -1; + + if (source.ip.family == AF_INET || source.ip.family == AF_INET6) { + conn->ip_port = source; + conn->direct_lastrecv_time = current_time(); + return 0; + } + + return -1; +} + + +/* Set function to be called when someone requests a new connection to us. + * + * The set function should return -1 on failure and 0 on success. + * + * n_c is only valid for the duration of this function. + */ void new_connection_handler(Net_Crypto *c, int (*new_connection_callback)(void *object, New_Connection *n_c), void *object) { @@ -606,10 +732,34 @@ static int handle_new_connection_handshake(Net_Crypto *c, IP_Port source, uint8_ n_c.cookie_length = COOKIE_LENGTH; if (handle_crypto_handshake(c, n_c.recv_nonce, n_c.peersessionpublic_key, n_c.public_key, n_c.cookie, data, length, - 0) != 0) + 0) != 0) { + free(n_c.cookie); return -1; + } - return c->new_connection_callback(c->new_connection_callback_object, &n_c); + int crypt_connection_id = getcryptconnection_id(c, n_c.public_key); + + if (crypt_connection_id != -1) { + int ret = -1; + Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); + + if (conn != 0 && (conn->status == CRYPTO_CONN_COOKIE_REQUESTING || conn->status == CRYPTO_CONN_HANDSHAKE_SENT)) { + memcpy(conn->recv_nonce, n_c.recv_nonce, crypto_box_NONCEBYTES); + memcpy(conn->peersessionpublic_key, n_c.peersessionpublic_key, crypto_box_PUBLICKEYBYTES); + encrypt_precompute(conn->peersessionpublic_key, conn->sessionsecret_key, conn->shared_key); + + conn->status = CRYPTO_CONN_NOT_CONFIRMED; + crypto_connection_add_source(c, crypt_connection_id, source); + ret = 0; + } + + free(n_c.cookie); + return ret; + } + + int ret = c->new_connection_callback(c->new_connection_callback_object, &n_c); + free(n_c.cookie); + return ret; } /* Accept a crypto connection. @@ -619,7 +769,6 @@ static int handle_new_connection_handshake(Net_Crypto *c, IP_Port source, uint8_ */ int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c) { - //TODO: do something with n_c->source. if (getcryptconnection_id(c, n_c->public_key) != -1) return -1; @@ -654,6 +803,7 @@ int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c) send_temp_packet(c, crypt_connection_id); conn->status = CRYPTO_CONN_NOT_CONFIRMED; + crypto_connection_add_source(c, crypt_connection_id, n_c->source); return crypt_connection_id; } @@ -688,7 +838,6 @@ int new_crypto_connection(Net_Crypto *c, uint8_t *real_public_key) } /* Set the DHT public key of the crypto connection. - * If one to that real public key already exists, return it. * * return -1 on failure. * return 0 on success. @@ -708,7 +857,7 @@ int set_conection_dht_public_key(Net_Crypto *c, int crypt_connection_id, uint8_t uint8_t cookie_request[COOKIE_REQUEST_LENGTH]; if (create_cookie_request(c, cookie_request, conn->dht_public_key, conn->public_key, - conn->cookie_request_number) != sizeof(cookie_request)) + conn->cookie_request_number, conn->shared_key) != sizeof(cookie_request)) return -1; if (new_temp_packet(c, crypt_connection_id, cookie_request, sizeof(cookie_request)) != 0) @@ -718,6 +867,101 @@ int set_conection_dht_public_key(Net_Crypto *c, int crypt_connection_id, uint8_t return 0; } +/* Set the direct ip of the crypto connection. + * + * return -1 on failure. + * return 0 on success. + */ +int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port) +{ + Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); + + if (conn == 0) + return -1; + + if (!ipport_equal(&ip_port, &conn->ip_port)) { + conn->ip_port = ip_port; + conn->direct_lastrecv_time = 0; + } + + return 0; +} + +/* Get the crypto connection id from the ip_port. + * + * return -1 on failure. + * return connection id on success. + */ +static int crypto_id_ip_port(Net_Crypto *c, IP_Port ip_port) +{ + uint32_t i; + + for (i = 0; i < c->crypto_connections_length; ++i) { + if (is_alive(c->crypto_connections[i].status)) + if (ipport_equal(&ip_port, &c->crypto_connections[i].ip_port)) + return i; + } + + return -1; +} + +#define CRYPTO_MIN_PACKET_SIZE (1 + sizeof(uint16_t) + crypto_box_MACBYTES) + +/* Handle raw UDP packets coming directly from the socket. + * + * Handles: + * Cookie response packets. + * Crypto handshake packets. + * Crypto data packets. + * + */ +static int udp_handle_packet(void *object, IP_Port source, uint8_t *packet, uint32_t length) +{ + if (length <= CRYPTO_MIN_PACKET_SIZE || length > MAX_CRYPTO_PACKET_SIZE) + return 1; + + Net_Crypto *c = object; + int crypt_connection_id = crypto_id_ip_port(c, source); + + if (crypt_connection_id == -1) { + if (packet[0] != NET_PACKET_CRYPTO_HS) + return 1; + + if (handle_new_connection_handshake(c, source, packet, length) != 0) + return 1; + + return 0; + } + + if (handle_packet_connection(c, crypt_connection_id, packet, length) != 0) + return 1; + + Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); + + if (conn == 0) + return -1; + + conn->direct_lastrecv_time = current_time(); + return 0; +} + +static void send_crypto_packets(Net_Crypto *c) +{ + uint32_t i; + uint64_t temp_time = current_time(); + + for (i = 0; i < c->crypto_connections_length; ++i) { + Crypto_Connection *conn = get_crypto_connection(c, i); + + if (conn == 0) + return; + + if ((CRYPTO_SEND_PACKET_INTERVAL * 1000UL) + conn->temp_packet_sent_time < temp_time) { + send_temp_packet(c, i); + } + } +} + /* return 0 if there is no received data in the buffer. * return -1 if the packet was discarded. * return length of received data if successful. @@ -1196,6 +1440,9 @@ Net_Crypto *new_net_crypto(DHT *dht) new_symmetric_key(temp->secret_symmetric_key); networking_registerhandler(dht->net, NET_PACKET_COOKIE_REQUEST, &udp_handle_cookie_request, temp); + networking_registerhandler(dht->net, NET_PACKET_COOKIE_RESPONSE, &udp_handle_packet, temp); + networking_registerhandler(dht->net, NET_PACKET_CRYPTO_HS, &udp_handle_packet, temp); + networking_registerhandler(dht->net, NET_PACKET_CRYPTO_DATA, &udp_handle_packet, temp); return temp; } diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index 0d27ae4d..736d3070 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -40,6 +40,10 @@ #define MAX_CRYPTO_PACKET_SIZE 1400 #define MAX_CRYPTO_DATA_SIZE (MAX_CRYPTO_PACKET_SIZE - (1 + sizeof(uint16_t) + crypto_box_MACBYTES)) + +/* Interval in ms between sending cookie request/handshake packets. */ +#define CRYPTO_SEND_PACKET_INTERVAL 500 + typedef struct { uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* The real public key of the peer. */ uint8_t recv_nonce[crypto_box_NONCEBYTES]; /* Nonce of received packets. */ @@ -64,6 +68,10 @@ typedef struct { uint8_t *temp_packet; /* Where the cookie request/handshake packet is stored while it is being sent. */ uint16_t temp_packet_length; uint64_t temp_packet_sent_time; /* The time at which the last temp_packet was sent in ms. */ + + IP_Port ip_port; /* The ip and port to contact this guy directly.*/ + uint64_t direct_lastrecv_time; /* The Time at which we last receive a direct packet. */ + } Crypto_Connection; typedef struct { From deb8bfc350748555b7de5d0f4911c382b3f2d65e Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 1 May 2014 19:42:44 -0400 Subject: [PATCH 045/117] Random number functions belong in crypto_core. --- toxcore/DHT.h | 1 + toxcore/Lossless_UDP.h | 1 + toxcore/crypto_core.c | 16 ++++++++++++++++ toxcore/crypto_core.h | 9 +++++++++ toxcore/network.c | 15 --------------- toxcore/network.h | 5 ----- 6 files changed, 27 insertions(+), 20 deletions(-) diff --git a/toxcore/DHT.h b/toxcore/DHT.h index c37511a1..52aad266 100644 --- a/toxcore/DHT.h +++ b/toxcore/DHT.h @@ -25,6 +25,7 @@ #define DHT_H #include "crypto_core.h" +#include "network.h" /* Size of the client_id in bytes. */ #define CLIENT_ID_SIZE crypto_box_PUBLICKEYBYTES diff --git a/toxcore/Lossless_UDP.h b/toxcore/Lossless_UDP.h index b23d602a..587cd9ff 100644 --- a/toxcore/Lossless_UDP.h +++ b/toxcore/Lossless_UDP.h @@ -25,6 +25,7 @@ #define LOSSLESS_UDP_H #include "network.h" +#include "crypto_core.h" #include "misc_tools.h" diff --git a/toxcore/crypto_core.c b/toxcore/crypto_core.c index 0b1971e7..6e92f5b6 100644 --- a/toxcore/crypto_core.c +++ b/toxcore/crypto_core.c @@ -50,6 +50,22 @@ int crypto_cmp(uint8_t *mem1, uint8_t *mem2, uint32_t length) return (1 & ((check - 1) >> 8)) - 1; } +/* return a random number. + */ +uint32_t random_int(void) +{ + uint32_t randnum; + randombytes((uint8_t *)&randnum , sizeof(randnum)); + return randnum; +} + +uint64_t random_64b(void) +{ + uint64_t randnum; + randombytes((uint8_t *)&randnum, sizeof(randnum)); + return randnum; +} + /* Precomputes the shared key from their public_key and our secret_key. * This way we can avoid an expensive elliptic curve scalar multiply for each * encrypt/decrypt operation. diff --git a/toxcore/crypto_core.h b/toxcore/crypto_core.h index c5969453..6b69f917 100644 --- a/toxcore/crypto_core.h +++ b/toxcore/crypto_core.h @@ -45,6 +45,15 @@ return -1 if they are not. */ int crypto_cmp(uint8_t *mem1, uint8_t *mem2, uint32_t length); +/* return a random number. + * + * random_int for a 32bin int. + * random_64b for a 64bit int. + */ +uint32_t random_int(void); +uint64_t random_64b(void); + + /* Encrypts plain of length length to encrypted of length + 16 using the * public key(32 bytes) of the receiver and the secret key of the sender and a 24 byte nonce. * diff --git a/toxcore/network.c b/toxcore/network.c index 6a7661c4..28925180 100644 --- a/toxcore/network.c +++ b/toxcore/network.c @@ -204,21 +204,6 @@ uint64_t current_time(void) #endif } -/* return a random number. - */ -uint32_t random_int(void) -{ - uint32_t randnum; - randombytes((uint8_t *)&randnum , sizeof(randnum)); - return randnum; -} - -uint64_t random_64b(void) -{ - uint64_t randnum; - randombytes((uint8_t *)&randnum, sizeof(randnum)); - return randnum; -} #ifdef LOGGING static void loglogdata(char *message, uint8_t *buffer, size_t buflen, IP_Port *ip_port, ssize_t res); diff --git a/toxcore/network.h b/toxcore/network.h index d19f144c..4a893cff 100644 --- a/toxcore/network.h +++ b/toxcore/network.h @@ -325,11 +325,6 @@ int set_socket_dualstack(sock_t sock); /* return current UNIX time in microseconds (us). */ uint64_t current_time(void); -/* return a random number. - */ -uint32_t random_int(void); -uint64_t random_64b(void); - /* Basic network functions: */ /* Function to send packet(data) of length length to ip_port. */ From 8e24771fc41597dd9e3e02a192eb0b5b43771ac1 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 2 May 2014 10:36:48 -0400 Subject: [PATCH 046/117] Remove Lossless UDP (This breaks Tox.) --- testing/Lossless_UDP_testclient.c | 260 ------- testing/Lossless_UDP_testserver.c | 237 ------ testing/Makefile.inc | 36 - toxcore/Lossless_UDP.c | 1168 ----------------------------- toxcore/Lossless_UDP.h | 262 ------- toxcore/Makefile.inc | 2 - toxcore/Messenger.c | 70 +- toxcore/Messenger.h | 1 + toxcore/net_crypto.c | 381 +--------- toxcore/net_crypto.h | 41 +- toxcore/tox.c | 2 +- 11 files changed, 60 insertions(+), 2400 deletions(-) delete mode 100644 testing/Lossless_UDP_testclient.c delete mode 100644 testing/Lossless_UDP_testserver.c delete mode 100644 toxcore/Lossless_UDP.c delete mode 100644 toxcore/Lossless_UDP.h diff --git a/testing/Lossless_UDP_testclient.c b/testing/Lossless_UDP_testclient.c deleted file mode 100644 index 535509e0..00000000 --- a/testing/Lossless_UDP_testclient.c +++ /dev/null @@ -1,260 +0,0 @@ -/* Lossless_UDP testclient - * A program that connects and sends a file using our lossless UDP algorithm. - * NOTE: this program simulates a 33% packet loss. - * - * Best used in combination with Lossless_UDP_testserver - * - * Compile with: gcc -O2 -Wall -lsodium -o testclient ../toxcore/network.c ../toxcore/Lossless_UDP.c ../toxcore/util.c Lossless_UDP_testclient.c - * - * Command line arguments are the ip and port to connect and send the file to. - * EX: ./testclient --ipv4 127.0.0.1 33445 filename.txt - * - * Copyright (C) 2013 Tox project All Rights Reserved. - * - * This file is part of Tox. - * - * Tox is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Tox is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Tox. If not, see . - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "../toxcore/network.h" -#include "../toxcore/Lossless_UDP.h" -#include "../toxcore/util.h" -#include "misc_tools.c" - -#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) - -#define c_sleep(x) Sleep(1*x) - -#else -#include -#include -#define c_sleep(x) usleep(1000*x) - -#endif - -#define PORT 33446 - -void printpacket(uint8_t *data, uint32_t length, IP_Port ip_port) -{ - uint32_t i; - printf("UNHANDLED PACKET RECEIVED\nLENGTH:%u\nCONTENTS:\n", length); - printf("--------------------BEGIN-----------------------------\n"); - - for (i = 0; i < length; i++) { - if (data[i] < 16) - printf("0"); - - printf("%hhX", data[i]); - } - - printf("\n--------------------END-----------------------------\n\n\n"); -} - -void printip(IP_Port ip_port) -{ - printf("\nIP: %s Port: %u", ip_ntoa(&ip_port.ip), ntohs(ip_port.port)); -} -/* -void printpackets(Data test) -{ - int i; - if(test.size == 0) - return; - printf("SIZE: %u\n", test.size); - for(i =0; i < test.size; i++) - { - printf("%hhX", test.data[i]); - } - printf("\n"); -} - -void printconnection(int connection_id) -{ - printf("--------------------BEGIN---------------------\n"); - IP_Port ip_port = connections[connection_id].ip_port; - printf("IP: %u.%u.%u.%u Port: %u\n",ip_port.ip.c[0],ip_port.ip.c[1],ip_port.ip.c[2],ip_port.ip.c[3],ntohs(ip_port.port)); - printf("status: %u, inbound: %u, SYNC_rate: %u\n", connections[connection_id].status, - connections[connection_id].inbound, connections[connection_id].SYNC_rate); - printf("data rate: %u, last sync: %llu, last sent: %llu, last recv: %llu \n", connections[connection_id].data_rate, - connections[connection_id].last_SYNC, connections[connection_id].last_sent, connections[connection_id].last_recv); - int i; - for(i =0; i < MAX_QUEUE_NUM; i++) - { - printf(" %u ",i); - printpackets(connections[connection_id].sendbuffer[i]); - } - for(i =0; i < MAX_QUEUE_NUM; i++) - { - printf(" %u ",i); - printpackets(connections[connection_id].recvbuffer[i]); - } - Data sendbuffer[MAX_QUEUE_NUM]; - Data recvbuffer[MAX_QUEUE_NUM]; - printf("recv_num: %u, orecv_num: %u, sent_packetnum %u, osent_packetnum: %u, successful_sent: %u, successful_read: %u\n", - connections[connection_id].recv_packetnum, - connections[connection_id].orecv_packetnum, connections[connection_id].sent_packetnum, connections[connection_id].osent_packetnum, - connections[connection_id].successful_sent, - connections[connection_id].successful_read); - - printf("req packets: \n"); - for(i = 0; i < BUFFER_PACKET_NUM; i++) - { - printf(" %u ", connections[connection_id].req_packets[i]); - } - printf("\nNumber: %u recv_counter: %u, send_counter: %u\n", connections[connection_id].num_req_paquets, - connections[connection_id].recv_counter, connections[connection_id].send_counter); - - printf("--------------------END---------------------\n"); - -} -*/ - -/*( receive packets and send them to the packethandler */ -/*run doLossless_UDP(); */ -//void Lossless_UDP() -//{ -/* IP_Port ip_port; - uint8_t data[MAX_UDP_PACKET_SIZE]; - uint32_t length; - while (receivepacket(&ip_port, data, &length) != -1) { - printf("packet with length: %u\n", length); */ -/* if(rand() % 3 != 1)//add packet loss - { */ -/* - if (LosslessUDP_handlepacket(data, length, ip_port)) - printpacket(data, length, ip_port); - else - printf("Received handled packet with length: %u\n", length); //printconnection(0); */ - -/* } */ -/* }*/ - -//networking_poll(); - -//doLossless_UDP(); - -//} - -int main(int argc, char *argv[]) -{ - /* let user override default by cmdline */ - uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; /* x */ - int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled); - - if (argvoffset < 0) - exit(1); - - if (argc < argvoffset + 4) { - printf("Usage: %s [--ipv4|--ipv6] ip port filename\n", argv[0]); - exit(0); - } - - uint8_t buffer[MAX_DATA_SIZE]; - int read; - - FILE *file = fopen(argv[argvoffset + 3], "rb"); - - if (file == NULL) { - printf("Failed to open file \"%s\".\n", argv[argvoffset + 3]); - return 1; - } - - - /* initialize networking */ - /* bind to ip 0.0.0.0:PORT */ - IP ip; - ip_init(&ip, ipv6enabled); - - Lossless_UDP *ludp = new_lossless_udp(new_networking(ip, PORT)); - perror("Initialization"); - - IP_Port serverip; - ip_init(&serverip.ip, ipv6enabled); - - if (!addr_resolve(argv[argvoffset + 1], &serverip.ip, NULL)) { - printf("Failed to convert \"%s\" into an IP address.\n", argv[argvoffset + 1]); - return 1; - } - - serverip.port = htons(atoi(argv[argvoffset + 2])); - printip(serverip); - - int connection = new_connection(ludp, serverip); - uint64_t timer = current_time(); - - while (1) { - /* printconnection(connection); */ - networking_poll(ludp->net); - do_lossless_udp(ludp); - - if (is_connected(ludp, connection) == LUDP_ESTABLISHED) { - printf("Connecting took: %llu us\n", (unsigned long long)(current_time() - timer)); - break; - } - - if (is_connected(ludp, connection) == LUDP_NO_CONNECTION) { - printf("Connection timeout after: %llu us\n", (unsigned long long)(current_time() - timer)); - return 1; - } - - c_sleep(1); - } - - timer = current_time(); - unsigned long long bytes_sent = 0; - - /*read first part of file */ - read = fread(buffer, 1, MAX_DATA_SIZE, file); - - while (1) { - /* printconnection(connection); */ - networking_poll(ludp->net); - do_lossless_udp(ludp); - - if (is_connected(ludp, connection) == LUDP_ESTABLISHED) { - - while (write_packet(ludp, connection, buffer, read)) { - bytes_sent += read; - /* printf("Wrote data.\n"); */ - read = fread(buffer, 1, MAX_DATA_SIZE, file); - - } - - /* printf("%u\n", sendqueue(connection)); */ - if (sendqueue(ludp, connection) == 0) { - if (read == 0) { - unsigned long long us = (unsigned long long)(current_time() - timer); - printf("Sent file successfully in: %llu us = %llu seconds. Average speed: %llu KB/s\n", us, us / 1000000UL, - bytes_sent / (us / 1024UL)); - //printf("Total bytes sent: %llu B, Total data sent: %llu B, overhead: %llu B\n", total_bytes_sent, bytes_sent, total_bytes_sent-bytes_sent); - break; - } - } - } else { - printf("%u Client Connecting Lost after: %llu us\n", is_connected(ludp, connection), - (unsigned long long)(current_time() - timer)); - return 0; - } - - } - - c_sleep(25); - - return 0; -} diff --git a/testing/Lossless_UDP_testserver.c b/testing/Lossless_UDP_testserver.c deleted file mode 100644 index dd4612f5..00000000 --- a/testing/Lossless_UDP_testserver.c +++ /dev/null @@ -1,237 +0,0 @@ -/* Lossless_UDP testserver - * A program that waits for a lossless UDP connection and then saves all the data received to a file. - * NOTE: this program simulates a 33% packet loss. - * - * Best used in combination with Lossless_UDP_testclient - * - * Compile with: gcc -O2 -Wall -lsodium -o testserver ../toxcore/network.c ../toxcore/Lossless_UDP.c ../toxcore/util.c Lossless_UDP_testserver.c - * - * Command line argument is the name of the file to save what we receive to. - * EX: ./testserver filename1.txt - * - * Copyright (C) 2013 Tox project All Rights Reserved. - * - * This file is part of Tox. - * - * Tox is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Tox is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Tox. If not, see . - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "../toxcore/network.h" -#include "../toxcore/Lossless_UDP.h" -#include "../toxcore/util.h" -#include "misc_tools.c" - -//Sleep function (x = milliseconds) -#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) - -#define c_sleep(x) Sleep(1*x) - -#else -#include -#include -#define c_sleep(x) usleep(1000*x) - -#endif - -#define PORT 33445 - -void printpacket(uint8_t *data, uint32_t length, IP_Port ip_port) -{ - uint32_t i; - printf("UNHANDLED PACKET RECEIVED\nLENGTH:%u\nCONTENTS:\n", length); - printf("--------------------BEGIN-----------------------------\n"); - - for (i = 0; i < length; i++) { - if (data[i] < 16) - printf("0"); - - printf("%hhX", data[i]); - } - - printf("\n--------------------END-----------------------------\n\n\n"); -} - -/* -void printpackets(Data test) -{ - int i; - if(test.size == 0) - return; - printf("SIZE: %u\n", test.size); - for(i =0; i < test.size; i++) - { - printf("%hhX", test.data[i]); - } - printf("\n"); -} - -void printconnection(int connection_id) -{ - printf("--------------------BEGIN---------------------\n"); - IP_Port ip_port = connections[connection_id].ip_port; - printf("IP: %u.%u.%u.%u Port: %u\n",ip_port.ip.c[0],ip_port.ip.c[1],ip_port.ip.c[2],ip_port.ip.c[3],ntohs(ip_port.port)); - printf("status: %u, inbound: %u, SYNC_rate: %u\n", connections[connection_id].status, - connections[connection_id].inbound, connections[connection_id].SYNC_rate); - printf("data rate: %u, last sync: %llu, last sent: %llu, last recv: %llu \n", connections[connection_id].data_rate, - connections[connection_id].last_SYNC, connections[connection_id].last_sent, connections[connection_id].last_recv); - int i; - for(i =0; i < MAX_QUEUE_NUM; i++) - { - printf(" %u ",i); - printpackets(connections[connection_id].sendbuffer[i]); - } - for(i =0; i < MAX_QUEUE_NUM; i++) - { - printf(" %u ",i); - printpackets(connections[connection_id].recvbuffer[i]); - } - Data sendbuffer[MAX_QUEUE_NUM]; - Data recvbuffer[MAX_QUEUE_NUM]; - printf("recv_num: %u, orecv_num: %u, sent_packetnum %u, osent_packetnum: %u, successful_sent: %u, successful_read: %u\n", - connections[connection_id].recv_packetnum, - connections[connection_id].orecv_packetnum, connections[connection_id].sent_packetnum, connections[connection_id].osent_packetnum, - connections[connection_id].successful_sent, - connections[connection_id].successful_read); - - printf("req packets: \n"); - for(i = 0; i < BUFFER_PACKET_NUM; i++) - { - printf(" %u ", connections[connection_id].req_packets[i]); - } - printf("\nNumber: %u recv_counter: %u, send_counter: %u\n", connections[connection_id].num_req_paquets, - connections[connection_id].recv_counter, connections[connection_id].send_counter); - - printf("--------------------END---------------------\n"); - -} -*/ - -/* receive packets and send them to the packethandler - * run doLossless_UDP(); */ -//void Lossless_UDP() -//{ -// IP_Port ip_port; -// uint8_t data[MAX_UDP_PACKET_SIZE]; -// uint32_t length; -// while (receivepacket(&ip_port, data, &length) != -1) { -//if(rand() % 3 != 1)//add packet loss -//{ -// if (LosslessUDP_handlepacket(data, length, ip_port)) { -// printpacket(data, length, ip_port); -// } else { -//printconnection(0); -// printf("Received handled packet with length: %u\n", length); -// } -//} -// } - -// networking_poll(); - -//doLossless_UDP(); -//} - - -int main(int argc, char *argv[]) -{ - /* let user override default by cmdline */ - uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; /* x */ - int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled); - - if (argvoffset < 0) - exit(1); - - if (argc < argvoffset + 2) { - printf("Usage: %s [--ipv4|--ipv6] filename\n", argv[0]); - exit(0); - } - - uint8_t buffer[MAX_DATA_SIZE]; - int read; - - FILE *file = fopen(argv[argvoffset + 1], "wb"); - - if (file == NULL) { - printf("Failed to open file \"%s\".\n", argv[argvoffset + 1]); - return 1; - } - - - //initialize networking - //bind to ip 0.0.0.0:PORT - IP ip; - ip_init(&ip, ipv6enabled); - - Lossless_UDP *ludp = new_lossless_udp(new_networking(ip, PORT)); - perror("Initialization"); - - int connection; - uint64_t timer = current_time(); - - while (1) { - networking_poll(ludp->net); - do_lossless_udp(ludp); - connection = incoming_connection(ludp, 0); - - if (connection != -1) { - if (is_connected(ludp, connection) == LUDP_NOT_CONFIRMED) { - printf("Received the connection.\n"); - - } - - break; - } - - c_sleep(1); - } - - timer = current_time(); - - while (1) { - //printconnection(0); - networking_poll(ludp->net); - - if (is_connected(ludp, connection) >= LUDP_NOT_CONFIRMED) { - confirm_connection(ludp, connection); - - while (1) { - read = read_packet(ludp, connection, buffer); - - if (read != 0) { - // printf("Received data.\n"); - if (!fwrite(buffer, read, 1, file)) - printf("file write error\n"); - } else { - break; - } - } - } - - do_lossless_udp(ludp); - - if (is_connected(ludp, connection) == LUDP_TIMED_OUT) { - printf("Server Connecting Lost after: %llu us\n", (unsigned long long)(current_time() - timer)); - fclose(file); - return 1; - } - - c_sleep(25); - } - - return 0; -} diff --git a/testing/Makefile.inc b/testing/Makefile.inc index 812a5be1..b3912033 100644 --- a/testing/Makefile.inc +++ b/testing/Makefile.inc @@ -22,8 +22,6 @@ endif if BUILD_TESTING noinst_PROGRAMS += DHT_test \ - Lossless_UDP_testclient \ - Lossless_UDP_testserver \ Messenger_test \ crypto_speed_test @@ -41,40 +39,6 @@ DHT_test_LDADD = $(LIBSODIUM_LDFLAGS) \ $(WINSOCK2_LIBS) -Lossless_UDP_testclient_SOURCES = \ - ../testing/Lossless_UDP_testclient.c - -Lossless_UDP_testclient_CFLAGS = \ - $(LIBSODIUM_CFLAGS) \ - $(NACL_CFLAGS) - -Lossless_UDP_testclient_LDADD = \ - $(LIBSODIUM_LDFLAGS) \ - $(NACL_LDFLAGS) \ - libtoxcore.la \ - $(LIBSODIUM_LIBS) \ - $(NACL_OBJECTS) \ - $(NACL_LIBS) \ - $(WINSOCK2_LIBS) - - -Lossless_UDP_testserver_SOURCES = \ - ../testing/Lossless_UDP_testserver.c - -Lossless_UDP_testserver_CFLAGS = \ - $(LIBSODIUM_CFLAGS) \ - $(NACL_CFLAGS) - -Lossless_UDP_testserver_LDADD = \ - $(LIBSODIUM_LDFLAGS) \ - $(NACL_LDFLAGS) \ - libtoxcore.la \ - $(LIBSODIUM_LIBS) \ - $(NACL_OBJECTS) \ - $(NACL_LIBS) \ - $(WINSOCK2_LIBS) - - Messenger_test_SOURCES = \ ../testing/Messenger_test.c diff --git a/toxcore/Lossless_UDP.c b/toxcore/Lossless_UDP.c deleted file mode 100644 index c0db8a10..00000000 --- a/toxcore/Lossless_UDP.c +++ /dev/null @@ -1,1168 +0,0 @@ -/* Lossless_UDP.c - * - * An implementation of the Lossless_UDP protocol as seen in http://wiki.tox.im/index.php/Lossless_UDP - * - * Copyright (C) 2013 Tox project All Rights Reserved. - * - * This file is part of Tox. - * - * Tox is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Tox is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Tox. If not, see . - * - */ - -/* - * TODO: clean this file a bit. - * There are a couple of useless variables to get rid of. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "Lossless_UDP.h" - -#define LUDP_CONNECTION_OUTBOUND 0 -#define LUDP_CONNECTION_INBOUND_HANDLED 1 -#define LUDP_CONNECTION_INBOUND 2 - -/* Functions */ - -/* - * Get connection id from IP_Port. - * - * return -1 if there are no connections like we are looking for. - * return id if it found it. - */ -int getconnection_id(Lossless_UDP *ludp, IP_Port ip_port) -{ - tox_array_for_each(&ludp->connections, Connection, tmp) { - if (tmp->status != LUDP_NO_CONNECTION && ipport_equal(&tmp->ip_port, &ip_port)) { - return tmp_i; - } - } - - return -1; -} - -/* Resize a queue - * return length of queue on success. - * return ~0 on failure. - */ -uint32_t resize_queue(Data **buffer, uint32_t length, uint32_t new_length, uint32_t min_packetnum, - uint32_t max_packetnum) -{ - if (MAX_QUEUE_NUM < new_length) - new_length = MAX_QUEUE_NUM; - - if (max_packetnum - min_packetnum > new_length) - return ~0; - - if (length == new_length) - return new_length; - - Data *temp = calloc(1, sizeof(Data) * new_length); - - if (temp == NULL) - return ~0; - - if (*buffer == NULL) { - *buffer = temp; - return new_length; - } - - uint32_t i; - - for (i = min_packetnum; i != max_packetnum; ++i) - memcpy(temp + (i % new_length), *buffer + (i % length), sizeof(Data)); - - free(*buffer); - *buffer = temp; - return new_length; -} - - - -/* - * Generate a handshake_id which depends on the ip_port. - * This function will always give one unique handshake_id per ip_port. - * - * TODO: make this better - */ - -static uint32_t randtable_initget(Lossless_UDP *ludp, uint32_t index, uint8_t value) -{ - if (ludp->randtable[index][value] == 0) - ludp->randtable[index][value] = random_int(); - - return ludp->randtable[index][value]; -} - -static uint32_t handshake_id(Lossless_UDP *ludp, IP_Port source) -{ - uint32_t id = 0, i = 0; - - uint8_t *uint8; - uint8 = (uint8_t *)&source.port; - id ^= randtable_initget(ludp, i, *uint8); - i++, uint8++; - id ^= randtable_initget(ludp, i, *uint8); - i++; - - if (source.ip.family == AF_INET) { - int k; - - for (k = 0; k < 4; k++) { - id ^= randtable_initget(ludp, i++, source.ip.ip4.uint8[k]); - } - } - - if (source.ip.family == AF_INET6) { - int k; - - for (k = 0; k < 16; k++) { - id ^= randtable_initget(ludp, i++, source.ip.ip6.uint8[k]); - } - } - - /* id can't be zero. */ - if (id == 0) - id = 1; - - return id; -} - -/* - * Change the handshake id associated with that ip_port. - * - * TODO: Make this better - */ -static void change_handshake(Lossless_UDP *ludp, IP_Port source) -{ - uint8_t rand; - - if (source.ip.family == AF_INET) { - rand = random_int() % 4; - } else if (source.ip.family == AF_INET6) { - rand = random_int() % 16; - } else { - return; - } - - /* Forced to be more robust against strange definitions of sa_family_t */ - ludp->randtable[2 + rand][((uint8_t *)&source.ip.ip6)[rand]] = random_int(); -} - -/* - * Initialize a new connection to ip_port - * - * return an integer corresponding to the connection id. - * return -1 if it could not initialize the connectiont - * If there already was an existing connection to that ip_port return its number. - */ -int new_connection(Lossless_UDP *ludp, IP_Port ip_port) -{ - int connection_id = getconnection_id(ludp, ip_port); - - if (connection_id != -1) { - confirm_connection(ludp, connection_id); - return connection_id; - } - - tox_array_for_each(&ludp->connections, Connection, tmp) { - if (tmp->status == LUDP_NO_CONNECTION) { - connection_id = tmp_i; - break; - } - } - - if (connection_id == -1) { - if (tox_array_push_ptr(&ludp->connections, 0) == 0) - return -1; - - connection_id = ludp->connections.len - 1; - } - - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - - memset(connection, 0, sizeof(Connection)); - - uint32_t handshake_id1 = handshake_id(ludp, ip_port); - /* Add randomness to timeout to prevent connections getting stuck in a loop. */ - uint8_t timeout = CONNECTION_TIMEOUT + rand() % CONNECTION_TIMEOUT; - - *connection = (Connection) { - .ip_port = ip_port, - .status = LUDP_HANDSHAKE_SENDING, - .inbound = LUDP_CONNECTION_OUTBOUND, - .handshake_id1 = handshake_id1, - .sent_packetnum = handshake_id1, - .sendbuff_packetnum = handshake_id1, - .successful_sent = handshake_id1, - .SYNC_rate = SYNC_RATE, - .data_rate = DATA_SYNC_RATE, - .last_recvSYNC = current_time(), - .last_sent = current_time(), - .killat = ~0, - .send_counter = 0, - .timeout = timeout, - .confirmed = 1 - }; - connection->sendbuffer_length = resize_queue(&connection->sendbuffer, 0, DEFAULT_QUEUE_NUM, 0, 0); - connection->recvbuffer_length = resize_queue(&connection->recvbuffer, 0, DEFAULT_QUEUE_NUM, 0, 0); - - if (connection->sendbuffer_length == (uint32_t)~0 || connection->recvbuffer_length == (uint32_t)~0) { - free(connection->sendbuffer); - free(connection->recvbuffer); - memset(connection, 0, sizeof(Connection)); - return -1; - } - - return connection_id; -} - -/* - * Initialize a new inbound connection from ip_port. - * - * return an integer corresponding to the connection id. - * return -1 if it could not initialize the connection. - */ -static int new_inconnection(Lossless_UDP *ludp, IP_Port ip_port) -{ - if (getconnection_id(ludp, ip_port) != -1) - return -1; /* TODO: return existing connection instead? */ - - int connection_id = -1; - tox_array_for_each(&ludp->connections, Connection, tmp) { - if (tmp->status == LUDP_NO_CONNECTION) { - connection_id = tmp_i; - break; - } - } - - if (connection_id == -1) { - if (tox_array_push_ptr(&ludp->connections, 0) == 0) - return -1; - - connection_id = ludp->connections.len - 1; - } - - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - memset(connection, 0, sizeof(Connection)); - /* Add randomness to timeout to prevent connections getting stuck in a loop. */ - uint8_t timeout = CONNECTION_TIMEOUT + rand() % CONNECTION_TIMEOUT; - - *connection = (Connection) { - .ip_port = ip_port, - .status = LUDP_NOT_CONFIRMED, - .inbound = LUDP_CONNECTION_INBOUND, - .SYNC_rate = SYNC_RATE, - .data_rate = DATA_SYNC_RATE, - .last_recvSYNC = current_time(), - .last_sent = current_time(), - .send_counter = 127, - - .timeout = timeout, - - /* If this connection isn't handled within the timeout kill it. */ - .killat = current_time() + 1000000ULL * timeout, - .confirmed = 0 - }; - connection->sendbuffer_length = resize_queue(&connection->sendbuffer, 0, DEFAULT_QUEUE_NUM, 0, 0); - connection->recvbuffer_length = resize_queue(&connection->recvbuffer, 0, DEFAULT_QUEUE_NUM, 0, 0); - - if (connection->sendbuffer_length == (uint32_t)~0 || connection->recvbuffer_length == (uint32_t)~0) { - free(connection->sendbuffer); - free(connection->recvbuffer); - memset(connection, 0, sizeof(Connection)); - return -1; - } - - return connection_id; -} - -/* - * return an integer corresponding to the next connection in our incoming connection list with at least numpackets in the recieve queue. - * return -1 if there are no new incoming connections in the list. - */ -int incoming_connection(Lossless_UDP *ludp, uint32_t numpackets) -{ - tox_array_for_each(&ludp->connections, Connection, tmp) { - if (tmp->inbound == LUDP_CONNECTION_INBOUND && tmp->recv_packetnum - tmp->successful_read >= numpackets) { - tmp->inbound = LUDP_CONNECTION_INBOUND_HANDLED; - return tmp_i; - } - } - return -1; -} -/* Try to free some memory from the connections array. */ -static void free_connections(Lossless_UDP *ludp) -{ - uint32_t i; - - for (i = ludp->connections.len; i != 0; --i) { - Connection *connection = &tox_array_get(&ludp->connections, i - 1, Connection); - - if (connection->status != LUDP_NO_CONNECTION) - break; - } - - if (ludp->connections.len == i) - return; - - return tox_array_pop(&ludp->connections, ludp->connections.len - i); -} -/* return -1 if it could not kill the connection. - * return 0 if killed successfully. - */ -int kill_connection(Lossless_UDP *ludp, int connection_id) -{ - if ((unsigned int)connection_id < ludp->connections.len) { - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - - if (connection->status != LUDP_NO_CONNECTION) { - connection->status = LUDP_NO_CONNECTION; - change_handshake(ludp, connection->ip_port); - free(connection->sendbuffer); - free(connection->recvbuffer); - memset(connection, 0, sizeof(Connection)); - free_connections(ludp); - return 0; - } - } - - return -1; -} - -/* - * timeout connection in seconds. - * - * return -1 if it can not kill the connection. - * return 0 if it will kill it. - */ -int timeout_connection_in(Lossless_UDP *ludp, int connection_id, uint32_t seconds) -{ - if ((unsigned int)connection_id < ludp->connections.len) { - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - - if (connection->status != LUDP_NO_CONNECTION) { - connection->killat = current_time() + 1000000ULL * seconds; - return 0; - } - } - - return -1; -} - -/* - * Check if connection is connected: - * - * return LUDP_NO_CONNECTION if not. - * return LUDP_HANDSHAKE_SENDING if attempting handshake. - * return LUDP_NOT_CONFIRMED if handshake is done. - * return LUDP_ESTABLISHED if fully connected. - * return LUDP_TIMED_OUT if timed out and waiting to be killed. - */ -int is_connected(Lossless_UDP *ludp, int connection_id) -{ - if ((unsigned int)connection_id < ludp->connections.len) - return tox_array_get(&ludp->connections, connection_id, Connection).status; - - return 0; -} - -/* Check if connection is confirmed. - * - * returns 1 if yes. - * returns 0 if no/failure. - */ -int connection_confirmed(Lossless_UDP *ludp, int connection_id) -{ - if ((unsigned int)connection_id >= ludp->connections.len) - return 0; - - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - - if (connection->status == LUDP_NO_CONNECTION) - return 0; - - if (connection->confirmed == 1) - return 1; - - return 0; -} - -/* Confirm an incoming connection. - * Also disable the auto kill timeout on incomming connections. - * - * return 0 on success - * return -1 on failure. - */ -int confirm_connection(Lossless_UDP *ludp, int connection_id) -{ - if ((unsigned int)connection_id >= ludp->connections.len) - return -1; - - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - - if (connection->status == LUDP_NO_CONNECTION) - return -1; - - connection->killat = ~0; - connection->confirmed = 1; - connection->inbound = LUDP_CONNECTION_OUTBOUND; - return 0; -} - -/* return the ip_port of the corresponding connection. */ -IP_Port connection_ip(Lossless_UDP *ludp, int connection_id) -{ - if ((unsigned int)connection_id < ludp->connections.len) - return tox_array_get(&ludp->connections, connection_id, Connection).ip_port; - - IP_Port zero; - ip_reset(&zero.ip); - zero.port = 0; - return zero; -} - -/* return the number of packets in the queue waiting to be successfully sent. */ -uint32_t sendqueue(Lossless_UDP *ludp, int connection_id) -{ - if ((unsigned int)connection_id >= ludp->connections.len) - return 0; - - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - - if (connection->status == LUDP_NO_CONNECTION) - return 0; - - return connection->sendbuff_packetnum - connection->successful_sent; -} - -/* return number of packets in all queues waiting to be successfully sent. */ -uint32_t sendqueue_total(Lossless_UDP *ludp) -{ - uint32_t i, total = 0; - - for (i = 0; i < ludp->connections.len; i++) { - Connection *connection = &tox_array_get(&ludp->connections, i, Connection); - - if (connection->status != 0) - total += connection->sendbuff_packetnum - connection->successful_sent; - } - - return total; -} - -/* return the number of packets in the queue waiting to be successfully read with read_packet(...). */ -uint32_t recvqueue(Lossless_UDP *ludp, int connection_id) -{ - if ((unsigned int)connection_id >= ludp->connections.len) - return 0; - - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - - if (connection->status == LUDP_NO_CONNECTION) - return 0; - - return connection->recv_packetnum - connection->successful_read; -} - -/* return the id of the next packet in the queue. - * return ~0 if no packet in queue. - */ -uint8_t id_packet(Lossless_UDP *ludp, int connection_id) -{ - if (recvqueue(ludp, connection_id) == 0) - return ~0; - - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - - if (connection->status != LUDP_NO_CONNECTION) - return connection->recvbuffer[connection->successful_read % connection->recvbuffer_length].data[0]; - - return ~0; -} - -/* return 0 if there is no received data in the buffer. - * return length of received packet if successful. - */ -int read_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data) -{ - if (recvqueue(ludp, connection_id) == 0) - return 0; - - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - - if (connection->status == LUDP_NO_CONNECTION) - return 0; - - uint16_t index = connection->successful_read % connection->recvbuffer_length; - uint16_t size = connection->recvbuffer[index].size; - memcpy(data, connection->recvbuffer[index].data, size); - ++connection->successful_read; - connection->recvbuffer[index].size = 0; - return size; -} - -/* Like read_packet() but does leaves the queue as is. - * return 0 if there is no received data in the buffer. - * return length of received packet if successful. - */ -int read_packet_silent(Lossless_UDP *ludp, int connection_id, uint8_t *data) -{ - if (recvqueue(ludp, connection_id) == 0) - return 0; - - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - - if (connection->status == LUDP_NO_CONNECTION) - return 0; - - uint16_t index = connection->successful_read % connection->recvbuffer_length; - uint16_t size = connection->recvbuffer[index].size; - memcpy(data, connection->recvbuffer[index].data, size); - return size; -} -/* Discard the next packet to be read from the queue - * return 0 if success. - * return -1 if failure. - */ -int discard_packet(Lossless_UDP *ludp, int connection_id) -{ - if (recvqueue(ludp, connection_id) == 0) - return -1; - - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - uint16_t index = connection->successful_read % connection->recvbuffer_length; - ++connection->successful_read; - connection->recvbuffer[index].size = 0; - return 0; -} - -#define MAX_SYNC_RATE 20 -#define MIN_SLOTS 16 -/* returns the number of packet slots left in the sendbuffer. - * return 0 if failure. - */ -uint32_t num_free_sendqueue_slots(Lossless_UDP *ludp, int connection_id) -{ - if ((unsigned int)connection_id >= ludp->connections.len) - return 0; - - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - uint32_t max_slots = (connection->data_rate / MAX_SYNC_RATE) * 1.5; - - if (max_slots > MAX_QUEUE_NUM) - max_slots = MAX_QUEUE_NUM; - - if (max_slots < MIN_SLOTS) - max_slots = MIN_SLOTS; - - if (sendqueue(ludp, connection_id) > max_slots) - return 0; - - return max_slots - sendqueue(ludp, connection_id); -} - - -/* return 0 if data could not be put in packet queue. - * return 1 if data was put into the queue. - */ -int write_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data, uint32_t length) -{ - if ((unsigned int)connection_id >= ludp->connections.len) - return 0; - - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - - if (connection->status == LUDP_NO_CONNECTION) - return 0; - - if (length > MAX_DATA_SIZE || length == 0 || sendqueue(ludp, connection_id) >= MAX_QUEUE_NUM) - return 0; - - if (num_free_sendqueue_slots(ludp, connection_id) == 0) - return 0; - - if (sendqueue(ludp, connection_id) >= connection->sendbuffer_length && connection->sendbuffer_length != 0) { - uint32_t newlen = connection->sendbuffer_length = resize_queue(&connection->sendbuffer, connection->sendbuffer_length, - connection->sendbuffer_length * 2, connection->successful_sent, connection->sendbuff_packetnum); - - if (newlen == (uint32_t)~0) - return 0; - - connection->sendbuffer_length = newlen; - return write_packet(ludp, connection_id, data, length); - } - - uint32_t index = connection->sendbuff_packetnum % connection->sendbuffer_length; - memcpy(connection->sendbuffer[index].data, data, length); - connection->sendbuffer[index].size = length; - connection->sendbuff_packetnum++; - return 1; -} - -/* Put the packet numbers the we are missing in requested and return the number. */ -static uint32_t missing_packets(Lossless_UDP *ludp, int connection_id, uint32_t *requested) -{ - if ((unsigned int)connection_id >= ludp->connections.len) - return 0; - - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - - /* Don't request packets if the buffer is full. */ - if (recvqueue(ludp, connection_id) >= (connection->recvbuffer_length - 1)) - return 0; - - uint32_t number = 0; - uint32_t i; - uint32_t temp; - - for (i = connection->recv_packetnum; - i != connection->osent_packetnum; - i++) { - if (connection->recvbuffer[i % connection->recvbuffer_length].size == 0) { - temp = htonl(i); - memcpy(requested + number, &temp, 4); - ++number; - } - - if (number >= MAX_REQUESTED_PACKETS) - return number; - } - - if (number == 0) - connection->recv_packetnum = connection->osent_packetnum; - - return number; -} - -/* - * BEGIN Packet sending functions. - * One per packet type. - * See http://wiki.tox.im/index.php/Lossless_UDP for more information. - */ - -static int send_handshake(Lossless_UDP *ludp, IP_Port ip_port, uint32_t handshake_id1, uint32_t handshake_id2) -{ - uint8_t packet[1 + 4 + 4]; - uint32_t temp; - - packet[0] = NET_PACKET_HANDSHAKE; - temp = htonl(handshake_id1); - memcpy(packet + 1, &temp, 4); - temp = htonl(handshake_id2); - memcpy(packet + 5, &temp, 4); - - return sendpacket(ludp->net, ip_port, packet, sizeof(packet)); -} - -static int send_SYNC(Lossless_UDP *ludp, int connection_id) -{ - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - uint8_t packet[(MAX_REQUESTED_PACKETS * 4 + 4 + 4 + 2)]; - uint16_t index = 0; - - IP_Port ip_port = connection->ip_port; - uint8_t counter = connection->send_counter; - uint32_t recv_packetnum = htonl(connection->recv_packetnum); - uint32_t sent_packetnum = htonl(connection->sent_packetnum); - - uint32_t requested[MAX_REQUESTED_PACKETS]; - uint32_t number = missing_packets(ludp, connection_id, requested); - - packet[0] = NET_PACKET_SYNC; - index += 1; - memcpy(packet + index, &counter, 1); - index += 1; - memcpy(packet + index, &recv_packetnum, 4); - index += 4; - memcpy(packet + index, &sent_packetnum, 4); - index += 4; - memcpy(packet + index, requested, 4 * number); - - return sendpacket(ludp->net, ip_port, packet, (number * 4 + 4 + 4 + 2)); - -} - -static int send_data_packet(Lossless_UDP *ludp, int connection_id, uint32_t packet_num) -{ - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - - uint32_t index = packet_num % connection->sendbuffer_length; - uint32_t temp; - uint8_t packet[1 + 4 + MAX_DATA_SIZE]; - packet[0] = NET_PACKET_DATA; - temp = htonl(packet_num); - memcpy(packet + 1, &temp, 4); - memcpy(packet + 5, connection->sendbuffer[index].data, connection->sendbuffer[index].size); - return sendpacket(ludp->net, connection->ip_port, packet, 1 + 4 + connection->sendbuffer[index].size); -} - -/* Sends 1 data packet. */ -static int send_DATA(Lossless_UDP *ludp, int connection_id) -{ - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - int ret; - uint32_t buffer[MAX_REQUESTED_PACKETS]; - - if (connection->num_req_paquets > 0) { - ret = send_data_packet(ludp, connection_id, connection->req_packets[0]); - connection->num_req_paquets--; - memcpy(buffer, connection->req_packets + 1, connection->num_req_paquets * 4); - memcpy(connection->req_packets, buffer, connection->num_req_paquets * 4); - return ret; - } - - if (connection->sendbuff_packetnum != connection->sent_packetnum) { - ret = send_data_packet(ludp, connection_id, connection->sent_packetnum); - connection->sent_packetnum++; - return ret; - } - - return 0; -} - -/* - * END of packet sending functions. - * - * - * BEGIN Packet handling functions. - * One to handle each type of packets we receive. - */ - - -/* return 0 if handled correctly. - * return 1 if packet is bad. - */ -static int handle_handshake(void *object, IP_Port source, uint8_t *packet, uint32_t length) -{ - Lossless_UDP *ludp = object; - - if (length != (1 + 4 + 4)) - return 1; - - uint32_t temp; - uint32_t handshake_id1, handshake_id2; - int connection_id = getconnection_id(ludp, source); - - memcpy(&temp, packet + 1, 4); - handshake_id1 = ntohl(temp); - memcpy(&temp, packet + 5, 4); - handshake_id2 = ntohl(temp); - - - if (handshake_id2 == 0 && is_connected(ludp, connection_id) != LUDP_ESTABLISHED && - is_connected(ludp, connection_id) != LUDP_TIMED_OUT) { - send_handshake(ludp, source, handshake_id(ludp, source), handshake_id1); - return 0; - } - - if (is_connected(ludp, connection_id) != LUDP_HANDSHAKE_SENDING) - return 1; - - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - - /* if handshake_id2 is what we sent previously as handshake_id1 */ - if (handshake_id2 == connection->handshake_id1) { - connection->status = LUDP_NOT_CONFIRMED; - /* NOTE: Is this necessary? - connection->handshake_id2 = handshake_id1; */ - connection->orecv_packetnum = handshake_id2; - connection->osent_packetnum = handshake_id1; - connection->recv_packetnum = handshake_id1; - connection->successful_read = handshake_id1; - } - - return 0; -} - -/* return 1 if sync packet is valid. - * return 0 if not. - */ -static int SYNC_valid(uint32_t length) -{ - if (length < 4 + 4 + 2) - return 0; - - if (length > (MAX_REQUESTED_PACKETS * 4 + 4 + 4 + 2) || - ((length - 4 - 4 - 2) % 4) != 0) - return 0; - - return 1; -} - -/* case 1 in handle_SYNC: */ -static int handle_SYNC1(Lossless_UDP *ludp, IP_Port source, uint32_t recv_packetnum, uint32_t sent_packetnum) -{ - if (handshake_id(ludp, source) == recv_packetnum) { - int connection_id = new_inconnection(ludp, source); - - if (connection_id != -1) { - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - connection->orecv_packetnum = recv_packetnum; - connection->sent_packetnum = recv_packetnum; - connection->sendbuff_packetnum = recv_packetnum; - connection->successful_sent = recv_packetnum; - connection->osent_packetnum = sent_packetnum; - connection->recv_packetnum = sent_packetnum; - connection->successful_read = sent_packetnum; - - return connection_id; - } - } - - return -1; -} - -/* case 2 in handle_SYNC: */ -static int handle_SYNC2(Lossless_UDP *ludp, int connection_id, uint8_t counter, uint32_t recv_packetnum, - uint32_t sent_packetnum) -{ - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - - if (recv_packetnum == connection->orecv_packetnum && sent_packetnum == connection->osent_packetnum) { - connection->status = LUDP_ESTABLISHED; - connection->recv_counter = counter; - ++connection->send_counter; - send_SYNC(ludp, connection_id); - return 0; - } - - return 1; -} - -/* - * Automatically adjusts send rates of data packets for optimal transmission. - * - * TODO: Improve this. - */ -static void adjust_datasendspeed(Connection *connection, uint32_t req_packets) -{ - /* if there are no packets in send buffer */ - if (connection->sendbuff_packetnum - connection->successful_sent == 0) { - connection->data_rate -= connection->data_rate / 8; - - if (connection->data_rate < DATA_SYNC_RATE) - connection->data_rate = DATA_SYNC_RATE; - - return; - } - - if (req_packets <= (connection->data_rate / connection->SYNC_rate) / 4 || req_packets <= 10) { - connection->data_rate += (connection->data_rate / 4) + 1; - - if (connection->data_rate > connection->sendbuffer_length * connection->SYNC_rate) - connection->data_rate = connection->sendbuffer_length * connection->SYNC_rate; - } else { - connection->data_rate -= connection->data_rate / 8; - } -} - - -/* case 3 in handle_SYNC: */ -static int handle_SYNC3(Lossless_UDP *ludp, int connection_id, uint8_t counter, uint32_t recv_packetnum, - uint32_t sent_packetnum, - uint32_t *req_packets, - uint16_t number) -{ - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - - uint8_t comp_counter = (counter - connection->recv_counter); - uint32_t i, temp; - /* uint32_t comp_1 = (recv_packetnum - connection->successful_sent); - uint32_t comp_2 = (sent_packetnum - connection->successful_read); */ - uint32_t comp_1 = (recv_packetnum - connection->orecv_packetnum); - uint32_t comp_2 = (sent_packetnum - connection->osent_packetnum); - - /* Packet valid. */ - if (comp_1 <= connection->sendbuffer_length && - comp_2 <= MAX_QUEUE_NUM && - comp_counter != 0 && comp_counter < 8) { - connection->orecv_packetnum = recv_packetnum; - connection->osent_packetnum = sent_packetnum; - connection->successful_sent = recv_packetnum; - connection->last_recvSYNC = current_time(); - - connection->recv_counter = counter; - - ++connection->send_counter; - - for (i = 0; i < number; ++i) { - temp = ntohl(req_packets[i]); - memcpy(connection->req_packets + i, &temp, sizeof(uint32_t)); - } - - connection->num_req_paquets = number; - adjust_datasendspeed(connection, number); - return 0; - } - - return 1; -} - -static int handle_SYNC(void *object, IP_Port source, uint8_t *packet, uint32_t length) -{ - Lossless_UDP *ludp = object; - - if (!SYNC_valid(length)) - return 1; - - uint8_t counter; - uint32_t temp; - uint32_t recv_packetnum, sent_packetnum; - uint16_t number = (length - 4 - 4 - 2) / 4; - uint32_t req_packets[number]; - - memcpy(&counter, packet + 1, 1); - memcpy(&temp, packet + 2, 4); - recv_packetnum = ntohl(temp); - memcpy(&temp, packet + 6, 4); - sent_packetnum = ntohl(temp); - - if (number != 0) - memcpy(req_packets, packet + 10, 4 * number); - - int connection_id = getconnection_id(ludp, source); - - if (connection_id == -1) - return handle_SYNC1(ludp, source, recv_packetnum, sent_packetnum); - - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - - if (connection->status == LUDP_NOT_CONFIRMED) - return handle_SYNC2(ludp, connection_id, counter, - recv_packetnum, sent_packetnum); - - if (connection->status == LUDP_ESTABLISHED) - return handle_SYNC3(ludp, connection_id, counter, recv_packetnum, - sent_packetnum, req_packets, number); - - return 0; -} - -/* - * Add a packet to the received buffer and set the recv_packetnum of the - * connection to its proper value. - * - * return 1 if data was too big. - * return 0 if not. - */ -static int add_recv(Lossless_UDP *ludp, int connection_id, uint32_t data_num, uint8_t *data, uint16_t size) -{ - if (size > MAX_DATA_SIZE) - return 1; - - Connection *connection = &tox_array_get(&ludp->connections, connection_id, Connection); - uint32_t i; - uint32_t test = data_num - connection->recv_packetnum; - - if (test > MAX_QUEUE_NUM) - return 0; - - if (test > connection->recvbuffer_length) { - if (connection->confirmed == 0) - return 0; - - uint32_t len = resize_queue(&connection->recvbuffer, connection->recvbuffer_length, test * 2, - connection->successful_read, connection->successful_read + connection->recvbuffer_length); - - if (len == (uint32_t)~0) - return 0; - - connection->recvbuffer_length = len; - } - - uint32_t maxnum = connection->successful_read + connection->recvbuffer_length; - uint32_t sent_packet = data_num - connection->osent_packetnum; - - for (i = connection->recv_packetnum; i != maxnum; ++i) { - if (i == data_num) { - memcpy(connection->recvbuffer[data_num % connection->recvbuffer_length].data, data, size); - - connection->recvbuffer[data_num % connection->recvbuffer_length].size = size; - connection->last_recvdata = current_time(); - - if (sent_packet < connection->recvbuffer_length) - connection->osent_packetnum = data_num; - - break; - } - } - - for (i = connection->recv_packetnum; i != maxnum; ++i) { - if (connection->recvbuffer[i % connection->recvbuffer_length].size != 0) - connection->recv_packetnum = i; - else - break; - } - - return 0; -} - -static int handle_data(void *object, IP_Port source, uint8_t *packet, uint32_t length) -{ - Lossless_UDP *ludp = object; - int connection_id = getconnection_id(ludp, source); - - /* Drop the data packet if connection is not connected. */ - if (connection_id == -1) - return 1; - - if (tox_array_get(&ludp->connections, connection_id, Connection).status != LUDP_ESTABLISHED) - return 1; - - if (length > 1 + 4 + MAX_DATA_SIZE || length < 1 + 4 + 1) - return 1; - - uint32_t temp; - uint32_t number; - uint16_t size = length - 1 - 4; - - memcpy(&temp, packet + 1, 4); - number = ntohl(temp); - - return add_recv(ludp, connection_id, number, packet + 5, size); -} - -/* - * END of packet handling functions. - */ - -Lossless_UDP *new_lossless_udp(Networking_Core *net) -{ - if (net == NULL) - return NULL; - - Lossless_UDP *temp = calloc(1, sizeof(Lossless_UDP)); - - if (temp == NULL) - return NULL; - - tox_array_init(&temp->connections, sizeof(Connection)); - - temp->net = net; - networking_registerhandler(net, NET_PACKET_HANDSHAKE, &handle_handshake, temp); - networking_registerhandler(net, NET_PACKET_SYNC, &handle_SYNC, temp); - networking_registerhandler(net, NET_PACKET_DATA, &handle_data, temp); - return temp; -} - -/* - * Send handshake requests. - * Handshake packets are sent at the same rate as SYNC packets. - */ -static void do_new(Lossless_UDP *ludp) -{ - uint64_t temp_time = current_time(); - - tox_array_for_each(&ludp->connections, Connection, tmp) { - if (tmp->status == LUDP_HANDSHAKE_SENDING && (tmp->last_sent + (1000000ULL / tmp->SYNC_rate)) <= temp_time) { - send_handshake(ludp, tmp->ip_port, tmp->handshake_id1, 0); - tmp->last_sent = temp_time; - } - - /* kill all timed out connections */ - if (tmp->status != LUDP_NO_CONNECTION && (tmp->last_recvSYNC + tmp->timeout * 1000000ULL) < temp_time - && tmp->status != LUDP_TIMED_OUT) { - tmp->status = LUDP_TIMED_OUT; - /* kill_connection(i); */ - } - - if (tmp->status != LUDP_NO_CONNECTION && tmp->killat < temp_time) - tmp->status = LUDP_TIMED_OUT; - - if (tmp->inbound == LUDP_CONNECTION_INBOUND && tmp->status == LUDP_TIMED_OUT) - kill_connection(ludp, tmp_i); - } -} - -static void do_SYNC(Lossless_UDP *ludp) -{ - uint64_t temp_time = current_time(); - - tox_array_for_each(&ludp->connections, Connection, tmp) { - if (tmp->status == LUDP_NOT_CONFIRMED || tmp->status == LUDP_ESTABLISHED) - if ((tmp->last_SYNC + (1000000ULL / tmp->SYNC_rate)) <= temp_time) { - send_SYNC(ludp, tmp_i); - tmp->last_SYNC = temp_time; - } - } -} - -static void do_data(Lossless_UDP *ludp) -{ - uint64_t j; - uint64_t temp_time = current_time(); - - tox_array_for_each(&ludp->connections, Connection, tmp) { - if (tmp->status == LUDP_ESTABLISHED && sendqueue(ludp, tmp_i) != 0 && - (tmp->last_sent + (1000000ULL / tmp->data_rate)) <= temp_time) { - for (j = tmp->last_sent; j < temp_time; j += (1000000ULL / tmp->data_rate)) - if (send_DATA(ludp, tmp_i) <= 0) - break; - - tmp->last_sent = temp_time; - - } - } -} - - - -/* - * Automatically adjusts send rates of packets for optimal transmission. - * - * TODO: Flow control. - */ -static void adjust_rates(Lossless_UDP *ludp) -{ - uint64_t temp_time = current_time(); - - tox_array_for_each(&ludp->connections, Connection, tmp) { - if (tmp->status == LUDP_HANDSHAKE_SENDING || tmp->status == LUDP_NOT_CONFIRMED) - tmp->SYNC_rate = MAX_SYNC_RATE; - - if (tmp->status == LUDP_ESTABLISHED) { - if (sendqueue(ludp, tmp_i) != 0) { - tmp->SYNC_rate = MAX_SYNC_RATE; - } else if (tmp->last_recvdata + 200000ULL > temp_time) { /* 200 ms */ - tmp->SYNC_rate = MAX_SYNC_RATE; - } else { - tmp->SYNC_rate = SYNC_RATE; - } - } - } -} - -/* Call this function a couple times per second. It is the main loop. */ -void do_lossless_udp(Lossless_UDP *ludp) -{ - do_new(ludp); - do_SYNC(ludp); - do_data(ludp); - adjust_rates(ludp); -} - -void kill_lossless_udp(Lossless_UDP *ludp) -{ - uint32_t i; - - for (i = 0; i < ludp->connections.len; ++i) - kill_connection(ludp, i); - - tox_array_delete(&ludp->connections); - free(ludp); -} diff --git a/toxcore/Lossless_UDP.h b/toxcore/Lossless_UDP.h deleted file mode 100644 index 587cd9ff..00000000 --- a/toxcore/Lossless_UDP.h +++ /dev/null @@ -1,262 +0,0 @@ -/* Lossless_UDP.h - * - * An implementation of the Lossless_UDP protocol as seen in http://wiki.tox.im/index.php/Lossless_UDP - * - * Copyright (C) 2013 Tox project All Rights Reserved. - * - * This file is part of Tox. - * - * Tox is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Tox is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Tox. If not, see . - * - */ - -#ifndef LOSSLESS_UDP_H -#define LOSSLESS_UDP_H - -#include "network.h" -#include "crypto_core.h" -#include "misc_tools.h" - - -/* Maximum length of the data in the data packets. */ -#define MAX_DATA_SIZE 1024 - -/* Maximum data packets in sent and receive queues. */ -#define MAX_QUEUE_NUM 1024 -#define DEFAULT_QUEUE_NUM 4 - -/* Maximum number of data packets in the buffer. */ -#define MAX_REQUESTED_PACKETS 256 - -/* Timeout per connection is randomly set between CONNECTION_TIMEOUT and 2*CONNECTION_TIMEOUT. */ -#define CONNECTION_TIMEOUT 5 - -/* Initial amount of sync/handshake packets to send per second. */ -#define SYNC_RATE 2 - -/* Initial send rate of data. */ -#define DATA_SYNC_RATE 30 - -typedef struct { - uint8_t data[MAX_DATA_SIZE]; - uint16_t size; -} Data; - -#define LUDP_NO_CONNECTION 0 -#define LUDP_HANDSHAKE_SENDING 1 -#define LUDP_NOT_CONFIRMED 2 -#define LUDP_ESTABLISHED 3 -#define LUDP_TIMED_OUT 4 - -typedef struct { - IP_Port ip_port; - - /* - * return LUDP_NO_CONNECTION if connection is dead. - * return LUDP_HANDSHAKE_SENDING if attempting handshake. - * return LUDP_NOT_CONFIRMED if handshake is done (we start sending SYNC packets). - * return LUDP_ESTABLISHED if we are sending SYNC packets and can send data. - * return LUDP_TIMED_OUT if the connection has timed out. - */ - uint8_t status; - - /* - * return 0 if connection was not initiated by someone else. - * return 1 if incoming_connection() has returned. - * return 2 if it has not. - */ - uint8_t inbound; - - uint16_t SYNC_rate; /* Current SYNC packet send rate packets per second. */ - uint32_t data_rate; /* Current data packet send rate packets per second. */ - - uint64_t last_SYNC; /* Time our last SYNC packet was sent. */ - uint64_t last_sent; /* Time our last data or handshake packet was sent. */ - uint64_t last_recvSYNC; /* Time we last received a SYNC packet from the other. */ - uint64_t last_recvdata; /* Time we last received a DATA packet from the other. */ - uint64_t killat; /* Time to kill the connection. */ - - Data *sendbuffer; /* packet send buffer. */ - uint32_t sendbuffer_length; - Data *recvbuffer; /* packet receive buffer. */ - uint32_t recvbuffer_length; - uint32_t handshake_id1; - uint32_t handshake_id2; - - /* Number of data packets received (also used as handshake_id1). */ - uint32_t recv_packetnum; - - /* Number of packets received by the other peer. */ - uint32_t orecv_packetnum; - - /* Number of data packets sent. */ - uint32_t sent_packetnum; - - /* Number of packets sent by the other peer. */ - uint32_t osent_packetnum; - - /* Number of latest packet written onto the sendbuffer. */ - uint32_t sendbuff_packetnum; - - /* We know all packets before that number were successfully sent. */ - uint32_t successful_sent; - - /* Packet number of last packet read with the read_packet function. */ - uint32_t successful_read; - - /* List of currently requested packet numbers(by the other person). */ - uint32_t req_packets[MAX_REQUESTED_PACKETS]; - - /* Total number of currently requested packets(by the other person). */ - uint16_t num_req_paquets; - - uint8_t recv_counter; - uint8_t send_counter; - uint8_t timeout; /* connection timeout in seconds. */ - - /* Is the connection confirmed or not? 1 if yes, 0 if no */ - uint8_t confirmed; -} Connection; - -typedef struct { - Networking_Core *net; - - tox_array connections; - - /* Table of random numbers used in handshake_id. */ - /* IPv6 (16) + port (2)*/ - uint32_t randtable[18][256]; -} Lossless_UDP; - -/* - * Initialize a new connection to ip_port. - * - * return an integer corresponding to the connection id. - * return -1 if it could not initialize the connection. - * return number if there already was an existing connection to that ip_port. - */ -int new_connection(Lossless_UDP *ludp, IP_Port ip_port); - -/* - * Get connection id from IP_Port. - * - * return -1 if there are no connections like we are looking for. - * return id if it found it . - */ -int getconnection_id(Lossless_UDP *ludp, IP_Port ip_port); - -/* - * return an integer corresponding to the next connection in our incoming connection list with at least numpackets in the recieve queue. - * return -1 if there are no new incoming connections in the list. - */ -int incoming_connection(Lossless_UDP *ludp, uint32_t numpackets); - -/* return -1 if it could not kill the connection. - * return 0 if killed successfully. - */ -int kill_connection(Lossless_UDP *ludp, int connection_id); - -/* - * timeout connection in seconds seconds. - * - * return -1 if it can not kill the connection. - * return 0 if it will kill it. - */ -int timeout_connection_in(Lossless_UDP *ludp, int connection_id, uint32_t seconds); - - -/* Check if connection is confirmed. - * - * returns 1 if yes. - * returns 0 if no. - */ -int connection_confirmed(Lossless_UDP *ludp, int connection_id); - -/* Confirm an incoming connection. - * Also disables the auto kill timeout on incomming connections. - * - * return 0 on success - * return -1 on failure. - */ -int confirm_connection(Lossless_UDP *ludp, int connection_id); - -/* returns the ip_port of the corresponding connection. - * return 0 if there is no such connection. - */ -IP_Port connection_ip(Lossless_UDP *ludp, int connection_id); - -/* returns the id of the next packet in the queue. - * return -1 if no packet in queue. - */ -uint8_t id_packet(Lossless_UDP *ludp, int connection_id); - -/* return 0 if there is no received data in the buffer. - * return length of received packet if successful. - */ -int read_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data); - -/* Like read_packet() but does leaves the queue as is. - * return 0 if there is no received data in the buffer. - * return length of received packet if successful. - */ -int read_packet_silent(Lossless_UDP *ludp, int connection_id, uint8_t *data); - -/* Discard the next packet to be read from the queue - * return 0 if success. - * return -1 if failure. - */ -int discard_packet(Lossless_UDP *ludp, int connection_id); - -/* returns the number of packet slots left in the sendbuffer. - * return 0 if failure. - */ -uint32_t num_free_sendqueue_slots(Lossless_UDP *ludp, int connection_id); - -/* return 0 if data could not be put in packet queue. - * return 1 if data was put into the queue. - */ -int write_packet(Lossless_UDP *ludp, int connection_id, uint8_t *data, uint32_t length); - -/* return number of packets in the queue waiting to be successfully sent. */ -uint32_t sendqueue(Lossless_UDP *ludp, int connection_id); - -/* return number of packets in all queues waiting to be successfully sent. */ -uint32_t sendqueue_total(Lossless_UDP *ludp); - -/* - * return number of packets in the queue waiting to be successfully - * read with read_packet(...). - */ -uint32_t recvqueue(Lossless_UDP *ludp, int connection_id); - -/* Check if connection is connected: - * - * return LUDP_NO_CONNECTION if not. - * return LUDP_HANDSHAKE_SENDING if attempting handshake. - * return LUDP_NOT_CONFIRMED if handshake is done. - * return LUDP_ESTABLISHED if fully connected. - * return LUDP_TIMED_OUT if timed out and wating to be killed. - */ -int is_connected(Lossless_UDP *ludp, int connection_id); - -/* Call this function a couple times per second. It is the main loop. */ -void do_lossless_udp(Lossless_UDP *ludp); - -/* This function sets up LosslessUDP packet handling. */ -Lossless_UDP *new_lossless_udp(Networking_Core *net); - -void kill_lossless_udp(Lossless_UDP *ludp); - - -#endif diff --git a/toxcore/Makefile.inc b/toxcore/Makefile.inc index 7723aeaf..926b4e3f 100644 --- a/toxcore/Makefile.inc +++ b/toxcore/Makefile.inc @@ -11,8 +11,6 @@ libtoxcore_la_SOURCES = ../toxcore/DHT.h \ ../toxcore/network.c \ ../toxcore/crypto_core.h \ ../toxcore/crypto_core.c \ - ../toxcore/Lossless_UDP.h \ - ../toxcore/Lossless_UDP.c \ ../toxcore/net_crypto.h \ ../toxcore/net_crypto.c \ ../toxcore/friend_requests.h \ diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 308cf14e..1a5c93aa 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -406,10 +406,10 @@ uint32_t m_sendmessage(Messenger *m, int32_t friendnumber, uint8_t *message, uin uint32_t m_sendmessage_withid(Messenger *m, int32_t friendnumber, uint32_t theid, uint8_t *message, uint32_t length) { - if (length >= (MAX_DATA_SIZE - sizeof(theid))) + if (length >= (MAX_CRYPTO_DATA_SIZE - sizeof(theid))) return 0; - uint8_t temp[MAX_DATA_SIZE]; + uint8_t temp[MAX_CRYPTO_DATA_SIZE]; theid = htonl(theid); memcpy(temp, &theid, sizeof(theid)); memcpy(temp + sizeof(theid), message, length); @@ -440,10 +440,10 @@ uint32_t m_sendaction(Messenger *m, int32_t friendnumber, uint8_t *action, uint3 uint32_t m_sendaction_withid(Messenger *m, int32_t friendnumber, uint32_t theid, uint8_t *action, uint32_t length) { - if (length >= (MAX_DATA_SIZE - sizeof(theid))) + if (length >= (MAX_CRYPTO_DATA_SIZE - sizeof(theid))) return 0; - uint8_t temp[MAX_DATA_SIZE]; + uint8_t temp[MAX_CRYPTO_DATA_SIZE]; theid = htonl(theid); memcpy(temp, &theid, sizeof(theid)); memcpy(temp + sizeof(theid), action, length); @@ -840,7 +840,7 @@ int write_cryptpacket_id(Messenger *m, int32_t friendnumber, uint8_t packet_id, if (friend_not_valid(m, friendnumber)) return 0; - if (length >= MAX_DATA_SIZE || m->friendlist[friendnumber].status != FRIEND_ONLINE) + if (length >= MAX_CRYPTO_DATA_SIZE || m->friendlist[friendnumber].status != FRIEND_ONLINE) return 0; uint8_t packet[length + 1]; @@ -888,7 +888,7 @@ static IP_Port get_friend_ipport(Messenger *m, int32_t friendnumber) if (is_cryptoconnected(m->net_crypto, crypt_id) != CRYPTO_CONN_ESTABLISHED) return zero; - return connection_ip(m->net_crypto->lossless_udp, m->net_crypto->crypto_connections[crypt_id].number); + return m->net_crypto->crypto_connections[crypt_id].ip_port; } /* returns the group number of the chat with public key group_public_key. @@ -1395,7 +1395,7 @@ int new_filesender(Messenger *m, int32_t friendnumber, uint64_t filesize, uint8_ int file_control(Messenger *m, int32_t friendnumber, uint8_t send_receive, uint8_t filenumber, uint8_t message_id, uint8_t *data, uint16_t length) { - if (length > MAX_DATA_SIZE - 3) + if (length > MAX_CRYPTO_DATA_SIZE - 3) return -1; if (friend_not_valid(m, friendnumber)) @@ -1412,7 +1412,7 @@ int file_control(Messenger *m, int32_t friendnumber, uint8_t send_receive, uint8 if (send_receive > 1) return -1; - uint8_t packet[MAX_DATA_SIZE]; + uint8_t packet[MAX_CRYPTO_DATA_SIZE]; packet[0] = send_receive; packet[1] = filenumber; packet[2] = message_id; @@ -1482,7 +1482,7 @@ int file_control(Messenger *m, int32_t friendnumber, uint8_t send_receive, uint8 */ int file_data(Messenger *m, int32_t friendnumber, uint8_t filenumber, uint8_t *data, uint16_t length) { - if (length > MAX_DATA_SIZE - 1) + if (length > MAX_CRYPTO_DATA_SIZE - 1) return -1; if (friend_not_valid(m, friendnumber)) @@ -1495,7 +1495,7 @@ int file_data(Messenger *m, int32_t friendnumber, uint8_t filenumber, uint8_t *d if (crypto_num_free_sendqueue_slots(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id) < MIN_SLOTS_FREE) return -1; - uint8_t packet[MAX_DATA_SIZE]; + uint8_t packet[MAX_CRYPTO_DATA_SIZE]; packet[0] = filenumber; memcpy(packet + 1, data, length); @@ -1738,6 +1738,23 @@ static void LANdiscovery(Messenger *m) } } +int handle_new_connections(void *object, New_Connection *n_c) +{ + Messenger *m = object; + int friend_id = getfriend_id(m, n_c->public_key); + + if (friend_id != -1) { + if (m->friendlist[friend_id].crypt_connection_id != -1) + return -1; + + m->friendlist[friend_id].crypt_connection_id = accept_crypto_connection(m->net_crypto, n_c); + set_friend_status(m, friend_id, FRIEND_CONFIRMED); + } + + return -1; +} + + /* Run this at startup. */ Messenger *new_messenger(uint8_t ipv6enabled) { @@ -1772,6 +1789,8 @@ Messenger *new_messenger(uint8_t ipv6enabled) return NULL; } + new_connection_handler(m->net_crypto, &handle_new_connections, m); + m->onion = new_onion(m->dht); m->onion_a = new_onion_announce(m->dht); m->onion_c = new_onion_client(m->net_crypto); @@ -1843,7 +1862,7 @@ void do_friends(Messenger *m) { uint32_t i; int len; - uint8_t temp[MAX_DATA_SIZE]; + uint8_t temp[MAX_CRYPTO_DATA_SIZE]; uint64_t temp_time = unix_time(); for (i = 0; i < m->numfriends; ++i) { @@ -2184,32 +2203,8 @@ void do_friends(Messenger *m) } } -void do_inbound(Messenger *m) -{ - uint8_t secret_nonce[crypto_box_NONCEBYTES]; - uint8_t public_key[crypto_box_PUBLICKEYBYTES]; - uint8_t session_key[crypto_box_PUBLICKEYBYTES]; - int inconnection = crypto_inbound(m->net_crypto, public_key, secret_nonce, session_key); - if (inconnection != -1) { - int friend_id = getfriend_id(m, public_key); - if (friend_id != -1) { - if (m_get_friend_connectionstatus(m, friend_id) == 1) { - kill_connection(m->net_crypto->lossless_udp, inconnection); - return; - } - - crypto_kill(m->net_crypto, m->friendlist[friend_id].crypt_connection_id); - m->friendlist[friend_id].crypt_connection_id = - accept_crypto_inbound(m->net_crypto, inconnection, public_key, secret_nonce, session_key); - - set_friend_status(m, friend_id, FRIEND_CONFIRMED); - } else { - kill_connection(m->net_crypto->lossless_udp, inconnection); - } - } -} #ifdef LOGGING #define DUMPING_CLIENTS_FRIENDS_EVERY_N_SECONDS 60UL @@ -2238,7 +2233,6 @@ void do_messenger(Messenger *m) do_net_crypto(m->net_crypto); do_onion_client(m->onion_c); do_friends(m); - do_inbound(m); do_allgroupchats(m); LANdiscovery(m); @@ -2381,7 +2375,9 @@ size_t wait_data_size() int wait_prepare_messenger(Messenger *m, uint8_t *data) { - return networking_wait_prepare(m->net, sendqueue_total(m->net_crypto->lossless_udp), data); + //TODO + //return networking_wait_prepare(m->net, sendqueue_total(m->net_crypto->lossless_udp), data); + return networking_wait_prepare(m->net, 1024, data); } int wait_execute_messenger(uint8_t *data, long seconds, long microseconds) diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 3d42e911..66ef39e5 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -34,6 +34,7 @@ #include "onion_client.h" #define MAX_NAME_LENGTH 128 +/* TODO: this must depend on other variable. */ #define MAX_STATUSMESSAGE_LENGTH 1007 #define FRIEND_ADDRESS_SIZE (crypto_box_PUBLICKEYBYTES + sizeof(uint32_t) + sizeof(uint16_t)) diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index ad41ce78..6dbb6258 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -705,7 +705,7 @@ static int crypto_connection_add_source(Net_Crypto *c, int crypt_connection_id, * * The set function should return -1 on failure and 0 on success. * - * n_c is only valid for the duration of this function. + * n_c is only valid for the duration of the function call. */ void new_connection_handler(Net_Crypto *c, int (*new_connection_callback)(void *object, New_Connection *n_c), void *object) @@ -968,31 +968,7 @@ static void send_crypto_packets(Net_Crypto *c) */ int read_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data) { - if (crypt_connection_id_not_valid(c, crypt_connection_id)) - return 0; - if (c->crypto_connections[crypt_connection_id].status != CRYPTO_CONN_ESTABLISHED) - return 0; - - uint8_t temp_data[MAX_DATA_SIZE]; - int length = read_packet(c->lossless_udp, c->crypto_connections[crypt_connection_id].number, temp_data); - - if (length == 0) - return 0; - - if (temp_data[0] != 3) - return -1; - - int len = decrypt_data_symmetric(c->crypto_connections[crypt_connection_id].shared_key, - c->crypto_connections[crypt_connection_id].recv_nonce, - temp_data + 1, length - 1, data); - - if (len != -1) { - increment_nonce(c->crypto_connections[crypt_connection_id].recv_nonce); - return len; - } - - return -1; } /* returns the number of packet slots left in the sendbuffer. @@ -1000,10 +976,7 @@ int read_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data) */ uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id) { - if (crypt_connection_id_not_valid(c, crypt_connection_id)) - return 0; - return num_free_sendqueue_slots(c->lossless_udp, c->crypto_connections[crypt_connection_id].number); } /* return 0 if data could not be put in packet queue. @@ -1011,93 +984,7 @@ uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id) */ int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length) { - if (crypt_connection_id_not_valid(c, crypt_connection_id)) - return 0; - if (length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES > MAX_DATA_SIZE - 1) - return 0; - - if (c->crypto_connections[crypt_connection_id].status != CRYPTO_CONN_ESTABLISHED) - return 0; - - uint8_t temp_data[MAX_DATA_SIZE]; - int len = encrypt_data_symmetric(c->crypto_connections[crypt_connection_id].shared_key, - c->crypto_connections[crypt_connection_id].sent_nonce, - data, length, temp_data + 1); - - if (len == -1) - return 0; - - temp_data[0] = 3; - - if (write_packet(c->lossless_udp, c->crypto_connections[crypt_connection_id].number, temp_data, len + 1) == 0) - return 0; - - increment_nonce(c->crypto_connections[crypt_connection_id].sent_nonce); - return 1; -} - - -/* Send a crypto handshake packet containing an encrypted secret nonce and session public key - * to peer with connection_id and public_key. - * The packet is encrypted with a random nonce which is sent in plain text with the packet. - */ -static int send_cryptohandshake(Net_Crypto *c, int connection_id, uint8_t *public_key, uint8_t *secret_nonce, - uint8_t *session_key) -{ - uint8_t temp_data[MAX_DATA_SIZE]; - uint8_t temp[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES]; - uint8_t nonce[crypto_box_NONCEBYTES]; - - new_nonce(nonce); - memcpy(temp, secret_nonce, crypto_box_NONCEBYTES); - memcpy(temp + crypto_box_NONCEBYTES, session_key, crypto_box_PUBLICKEYBYTES); - - int len = encrypt_data(public_key, c->self_secret_key, nonce, temp, crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, - 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + temp_data); - - if (len == -1) - return 0; - - temp_data[0] = 2; - memcpy(temp_data + 1, c->self_public_key, crypto_box_PUBLICKEYBYTES); - memcpy(temp_data + 1 + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES); - return write_packet(c->lossless_udp, connection_id, temp_data, - len + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES); -} - -/* Extract secret nonce, session public key and public_key from a packet(data) with length length. - * - * return 1 if successful. - * return 0 if failure. - */ -static int handle_cryptohandshake(Net_Crypto *c, uint8_t *public_key, uint8_t *secret_nonce, - uint8_t *session_key, uint8_t *data, uint16_t length) -{ - int pad = (- crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES); - - if (length != 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES - + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + pad) { - return 0; - } - - if (data[0] != 2) - return 0; - - uint8_t temp[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES]; - - memcpy(public_key, data + 1, crypto_box_PUBLICKEYBYTES); - - int len = decrypt_data(public_key, c->self_secret_key, data + 1 + crypto_box_PUBLICKEYBYTES, - data + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, - crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + pad, temp); - - if (len != crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES) - return 0; - - memcpy(secret_nonce, temp, crypto_box_NONCEBYTES); - memcpy(session_key, temp + crypto_box_NONCEBYTES, crypto_box_PUBLICKEYBYTES); - return 1; } @@ -1108,92 +995,7 @@ static int handle_cryptohandshake(Net_Crypto *c, uint8_t *public_key, uint8_t *s */ int crypto_connect(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port) { - uint32_t i; - int id_existing = getcryptconnection_id(c, public_key); - if (id_existing != -1) { - IP_Port c_ip = connection_ip(c->lossless_udp, c->crypto_connections[id_existing].number); - - if (ipport_equal(&c_ip, &ip_port)) - return -1; - } - - if (realloc_cryptoconnection(c, c->crypto_connections_length + 1) == -1 - || c->crypto_connections == NULL) - return -1; - - memset(&(c->crypto_connections[c->crypto_connections_length]), 0, sizeof(Crypto_Connection)); - c->crypto_connections[c->crypto_connections_length].number = ~0; - - for (i = 0; i <= c->crypto_connections_length; ++i) { - if (c->crypto_connections[i].status == CRYPTO_CONN_NO_CONNECTION) { - int id_new = new_connection(c->lossless_udp, ip_port); - - if (id_new == -1) - return -1; - - c->crypto_connections[i].number = id_new; - c->crypto_connections[i].status = CRYPTO_CONN_HANDSHAKE_SENT; - random_nonce(c->crypto_connections[i].recv_nonce); - memcpy(c->crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES); - crypto_box_keypair(c->crypto_connections[i].sessionpublic_key, c->crypto_connections[i].sessionsecret_key); - c->crypto_connections[i].timeout = unix_time() + CRYPTO_HANDSHAKE_TIMEOUT; - - if (c->crypto_connections_length == i) - ++c->crypto_connections_length; - - if (send_cryptohandshake(c, id_new, public_key, c->crypto_connections[i].recv_nonce, - c->crypto_connections[i].sessionpublic_key) == 1) { - increment_nonce(c->crypto_connections[i].recv_nonce); - return i; - } - - return -1; /* This should never happen. */ - } - } - - return -1; -} - -/* Handle an incoming connection. - * - * return -1 if no crypto inbound connection. - * return incoming connection id (Lossless_UDP one) if there is an incoming crypto connection. - * - * Put the public key of the peer in public_key, the secret_nonce from the handshake into secret_nonce - * and the session public key for the connection in session_key. - * to accept it see: accept_crypto_inbound(...). - * to refuse it just call kill_connection(...) on the connection id. - */ -int crypto_inbound(Net_Crypto *c, uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_key) -{ - while (1) { - int incoming_con = incoming_connection(c->lossless_udp, 1); - - if (incoming_con != -1) { - if (is_connected(c->lossless_udp, incoming_con) == LUDP_TIMED_OUT) { - kill_connection(c->lossless_udp, incoming_con); - continue; - } - - if (id_packet(c->lossless_udp, incoming_con) == 2) { - uint8_t temp_data[MAX_DATA_SIZE]; - uint16_t len = read_packet_silent(c->lossless_udp, incoming_con, temp_data); - - if (handle_cryptohandshake(c, public_key, secret_nonce, session_key, temp_data, len)) { - return incoming_con; - } else { - kill_connection(c->lossless_udp, incoming_con); - } - } else { - kill_connection(c->lossless_udp, incoming_con); - } - } else { - break; - } - } - - return -1; } /* Kill a crypto connection. @@ -1203,94 +1005,7 @@ int crypto_inbound(Net_Crypto *c, uint8_t *public_key, uint8_t *secret_nonce, ui */ int crypto_kill(Net_Crypto *c, int crypt_connection_id) { - if (crypt_connection_id_not_valid(c, crypt_connection_id)) - return 1; - if (c->crypto_connections[crypt_connection_id].status != CRYPTO_CONN_NO_CONNECTION) { - c->crypto_connections[crypt_connection_id].status = CRYPTO_CONN_NO_CONNECTION; - kill_connection(c->lossless_udp, c->crypto_connections[crypt_connection_id].number); - memset(&(c->crypto_connections[crypt_connection_id]), 0 , sizeof(Crypto_Connection)); - c->crypto_connections[crypt_connection_id].number = ~0; - uint32_t i; - - for (i = c->crypto_connections_length; i != 0; --i) { - if (c->crypto_connections[i - 1].status != CRYPTO_CONN_NO_CONNECTION) - break; - } - - if (c->crypto_connections_length != i) { - c->crypto_connections_length = i; - realloc_cryptoconnection(c, c->crypto_connections_length); - } - - return 0; - } - - return 1; -} - -/* Accept an incoming connection using the parameters provided by crypto_inbound. - * - * return -1 if not successful. - * return the crypt_connection_id if successful. - */ -int accept_crypto_inbound(Net_Crypto *c, int connection_id, uint8_t *public_key, uint8_t *secret_nonce, - uint8_t *session_key) -{ - uint32_t i; - - if (discard_packet(c->lossless_udp, connection_id) == -1) - return -1; - - /* - * if(getcryptconnection_id(public_key) != -1) - * { - * return -1; - * } - */ - - if (realloc_cryptoconnection(c, c->crypto_connections_length + 1) == -1 - || c->crypto_connections == NULL) - return -1; - - memset(&(c->crypto_connections[c->crypto_connections_length]), 0, sizeof(Crypto_Connection)); - c->crypto_connections[c->crypto_connections_length].number = ~0; - - for (i = 0; i <= c->crypto_connections_length; ++i) { - if (c->crypto_connections[i].status == CRYPTO_CONN_NO_CONNECTION) { - c->crypto_connections[i].number = connection_id; - c->crypto_connections[i].status = CRYPTO_CONN_NOT_CONFIRMED; - c->crypto_connections[i].timeout = unix_time() + CRYPTO_HANDSHAKE_TIMEOUT; - random_nonce(c->crypto_connections[i].recv_nonce); - memcpy(c->crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES); - memcpy(c->crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES); - increment_nonce(c->crypto_connections[i].sent_nonce); - memcpy(c->crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES); - - crypto_box_keypair(c->crypto_connections[i].sessionpublic_key, c->crypto_connections[i].sessionsecret_key); - - if (c->crypto_connections_length == i) - ++c->crypto_connections_length; - - if (send_cryptohandshake(c, connection_id, public_key, c->crypto_connections[i].recv_nonce, - c->crypto_connections[i].sessionpublic_key) == 1) { - increment_nonce(c->crypto_connections[i].recv_nonce); - uint32_t zero = 0; - encrypt_precompute(c->crypto_connections[i].peersessionpublic_key, - c->crypto_connections[i].sessionsecret_key, - c->crypto_connections[i].shared_key); - c->crypto_connections[i].status = - CRYPTO_CONN_ESTABLISHED; /* Connection status needs to be 3 for write_cryptpacket() to work. */ - write_cryptpacket(c, i, ((uint8_t *)&zero), sizeof(zero)); - c->crypto_connections[i].status = CRYPTO_CONN_NOT_CONFIRMED; /* Set it to its proper value right after. */ - return i; - } - - return -1; /* This should never happen. */ - } - } - - return -1; } /* return 0 if no connection. @@ -1333,84 +1048,7 @@ void load_keys(Net_Crypto *c, uint8_t *keys) /* Handle received packets for not yet established crypto connections. */ static void receive_crypto(Net_Crypto *c) { - uint32_t i; - uint64_t temp_time = unix_time(); - for (i = 0; i < c->crypto_connections_length; ++i) { - if (c->crypto_connections[i].status == CRYPTO_CONN_NO_CONNECTION) - continue; - - if (c->crypto_connections[i].status == CRYPTO_CONN_HANDSHAKE_SENT) { - uint8_t temp_data[MAX_DATA_SIZE]; - uint8_t secret_nonce[crypto_box_NONCEBYTES]; - uint8_t public_key[crypto_box_PUBLICKEYBYTES]; - uint8_t session_key[crypto_box_PUBLICKEYBYTES]; - uint16_t len; - - if (id_packet(c->lossless_udp, c->crypto_connections[i].number) == 2) { /* Handle handshake packet. */ - len = read_packet(c->lossless_udp, c->crypto_connections[i].number, temp_data); - - if (handle_cryptohandshake(c, public_key, secret_nonce, session_key, temp_data, len)) { - if (memcmp(public_key, c->crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) { - memcpy(c->crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES); - memcpy(c->crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES); - increment_nonce(c->crypto_connections[i].sent_nonce); - uint32_t zero = 0; - encrypt_precompute(c->crypto_connections[i].peersessionpublic_key, - c->crypto_connections[i].sessionsecret_key, - c->crypto_connections[i].shared_key); - c->crypto_connections[i].status = - CRYPTO_CONN_ESTABLISHED; /* Connection status needs to be 3 for write_cryptpacket() to work. */ - write_cryptpacket(c, i, ((uint8_t *)&zero), sizeof(zero)); - c->crypto_connections[i].status = CRYPTO_CONN_NOT_CONFIRMED; /* Set it to its proper value right after. */ - } else { - /* This should not happen, timeout the connection if it does. */ - c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT; - } - } else { - /* This should not happen, timeout the connection if it does. */ - c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT; - } - } else if (id_packet(c->lossless_udp, - c->crypto_connections[i].number) != (uint8_t)~0) { - /* This should not happen, timeout the connection if it does. */ - c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT; - } - } - - if (c->crypto_connections[i].status == CRYPTO_CONN_NOT_CONFIRMED) { - if (id_packet(c->lossless_udp, c->crypto_connections[i].number) == 3) { - uint8_t temp_data[MAX_DATA_SIZE]; - uint8_t data[MAX_DATA_SIZE]; - int length = read_packet(c->lossless_udp, c->crypto_connections[i].number, temp_data); - int len = decrypt_data(c->crypto_connections[i].peersessionpublic_key, - c->crypto_connections[i].sessionsecret_key, - c->crypto_connections[i].recv_nonce, temp_data + 1, length - 1, data); - uint32_t zero = 0; - - if (len == sizeof(uint32_t) && memcmp(((uint8_t *)&zero), data, sizeof(uint32_t)) == 0) { - increment_nonce(c->crypto_connections[i].recv_nonce); - encrypt_precompute(c->crypto_connections[i].peersessionpublic_key, - c->crypto_connections[i].sessionsecret_key, - c->crypto_connections[i].shared_key); - c->crypto_connections[i].status = CRYPTO_CONN_ESTABLISHED; - c->crypto_connections[i].timeout = ~0; - /* Connection is accepted. */ - confirm_connection(c->lossless_udp, c->crypto_connections[i].number); - } else { - /* This should not happen, timeout the connection if it does. */ - c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT; - } - } else if (id_packet(c->lossless_udp, c->crypto_connections[i].number) != (uint8_t)~0) { - /* This should not happen, timeout the connection if it does. */ - c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT; - } - } - - if (temp_time > c->crypto_connections[i].timeout) { - c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT; - } - } } /* Run this to (re)initialize net_crypto. @@ -1429,12 +1067,6 @@ Net_Crypto *new_net_crypto(DHT *dht) return NULL; temp->dht = dht; - temp->lossless_udp = new_lossless_udp(dht->net); - - if (temp->lossless_udp == NULL) { - free(temp); - return NULL; - } new_keys(temp); new_symmetric_key(temp->secret_symmetric_key); @@ -1451,9 +1083,7 @@ static void kill_timedout(Net_Crypto *c) uint32_t i; for (i = 0; i < c->crypto_connections_length; ++i) { - if (c->crypto_connections[i].status != CRYPTO_CONN_NO_CONNECTION - && is_connected(c->lossless_udp, c->crypto_connections[i].number) == LUDP_TIMED_OUT) - c->crypto_connections[i].status = CRYPTO_CONN_TIMED_OUT; +//TODO } } @@ -1461,9 +1091,9 @@ static void kill_timedout(Net_Crypto *c) void do_net_crypto(Net_Crypto *c) { unix_time_update(); - do_lossless_udp(c->lossless_udp); kill_timedout(c); receive_crypto(c); + send_crypto_packets(c); } void kill_net_crypto(Net_Crypto *c) @@ -1474,7 +1104,10 @@ void kill_net_crypto(Net_Crypto *c) crypto_kill(c, i); } - kill_lossless_udp(c->lossless_udp); + networking_registerhandler(c->dht->net, NET_PACKET_COOKIE_REQUEST, NULL, NULL); + networking_registerhandler(c->dht->net, NET_PACKET_COOKIE_RESPONSE, NULL, NULL); + networking_registerhandler(c->dht->net, NET_PACKET_CRYPTO_HS, NULL, NULL); + networking_registerhandler(c->dht->net, NET_PACKET_CRYPTO_DATA, NULL, NULL); memset(c, 0, sizeof(Net_Crypto)); free(c); } diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index 736d3070..3d58e5c1 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -24,7 +24,6 @@ #ifndef NET_CRYPTO_H #define NET_CRYPTO_H -#include "Lossless_UDP.h" #include "DHT.h" #define CRYPTO_HANDSHAKE_TIMEOUT (CONNECTION_TIMEOUT * 2) @@ -39,6 +38,8 @@ #define CRYPTO_PACKET_BUFFER_SIZE 64 #define MAX_CRYPTO_PACKET_SIZE 1400 + +/* Max size of data in packets TODO*/ #define MAX_CRYPTO_DATA_SIZE (MAX_CRYPTO_PACKET_SIZE - (1 + sizeof(uint16_t) + crypto_box_MACBYTES)) /* Interval in ms between sending cookie request/handshake packets. */ @@ -58,7 +59,6 @@ typedef struct { * 4 if the connection is established. * 5 if the connection is timed out. */ - uint16_t number; /* Lossless_UDP connection number corresponding to this connection. */ uint64_t timeout; uint64_t cookie_request_number; /* number used in the cookie request packets for this connection */ @@ -71,7 +71,6 @@ typedef struct { IP_Port ip_port; /* The ip and port to contact this guy directly.*/ uint64_t direct_lastrecv_time; /* The Time at which we last receive a direct packet. */ - } Crypto_Connection; typedef struct { @@ -84,7 +83,6 @@ typedef struct { } New_Connection; typedef struct { - Lossless_UDP *lossless_udp; DHT *dht; Crypto_Connection *crypto_connections; @@ -103,6 +101,22 @@ typedef struct { } Net_Crypto; +/* Set function to be called when someone requests a new connection to us. + * + * The set function should return -1 on failure and 0 on success. + * + * n_c is only valid for the duration of the function call. + */ +void new_connection_handler(Net_Crypto *c, int (*new_connection_callback)(void *object, New_Connection *n_c), + void *object); + +/* Accept a crypto connection. + * + * return -1 on failure. + * return connection id on success. + */ +int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c); + /* return 0 if there is no received data in the buffer. * return -1 if the packet was discarded. @@ -134,25 +148,6 @@ int crypto_connect(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port); */ int crypto_kill(Net_Crypto *c, int crypt_connection_id); -/* Handle an incoming connection. - * - * return -1 if no crypto inbound connection. - * return incoming connection id (Lossless_UDP one) if there is an incoming crypto connection. - * - * Put the public key of the peer in public_key, the secret_nonce from the handshake into secret_nonce - * and the session public key for the connection in session_key. - * to accept it see: accept_crypto_inbound(...). - * to refuse it just call kill_connection(...) on the connection id. - */ -int crypto_inbound(Net_Crypto *c, uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_key); - -/* Accept an incoming connection using the parameters provided by crypto_inbound. - * - * return -1 if not successful. - * return crypt_connection_id if successful. - */ -int accept_crypto_inbound(Net_Crypto *c, int connection_id, uint8_t *public_key, uint8_t *secret_nonce, - uint8_t *session_key); /* return 0 if no connection. * return 1 we have sent a handshake diff --git a/toxcore/tox.c b/toxcore/tox.c index 6bd24e92..037cb7f5 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -721,7 +721,7 @@ int tox_file_send_data(Tox *tox, int32_t friendnumber, uint8_t filenumber, uint8 */ int tox_file_data_size(Tox *tox, int32_t friendnumber) { - return MAX_DATA_SIZE - crypto_box_MACBYTES - 3; + return MAX_CRYPTO_DATA_SIZE - 3; } /* Give the number of bytes left to be sent/received. From aca18f65c38c41fce73f50252d6c38c3b8fce9e5 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 2 May 2014 15:13:10 -0400 Subject: [PATCH 047/117] Small fixes. --- toxcore/net_crypto.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 6dbb6258..1dce61b2 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -385,7 +385,7 @@ static int send_data_packet(Net_Crypto *c, int crypt_connection_id, uint8_t *dat /* Get the lowest 2 bytes from the nonce and convert * them to host byte format before returning them. */ -uint16_t get_nonce_uint16(uint8_t *nonce) +static uint16_t get_nonce_uint16(uint8_t *nonce) { uint16_t num; memcpy(&num, nonce + (crypto_box_NONCEBYTES - sizeof(uint16_t)), sizeof(uint16_t)); @@ -618,7 +618,7 @@ static int create_crypto_connection(Net_Crypto *c) { uint32_t i; - for (i = 0; i <= c->crypto_connections_length; ++i) { + for (i = 0; i < c->crypto_connections_length; ++i) { if (c->crypto_connections[i].status == CRYPTO_CONN_NO_CONNECTION) return i; } From 8b29ac8eae8feea8b2c12e56482dd8845e8c7d35 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 2 May 2014 15:25:18 -0400 Subject: [PATCH 048/117] Fixed one case of the handshake not being sent. --- toxcore/net_crypto.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 1dce61b2..d71ccdda 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -560,6 +560,19 @@ static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, uint encrypt_precompute(conn->peersessionpublic_key, conn->sessionsecret_key, conn->shared_key); + if (conn->status == CRYPTO_CONN_COOKIE_REQUESTING) { + uint8_t handshake_packet[HANDSHAKE_PACKET_LENGTH]; + + if (create_crypto_handshake(c, handshake_packet, cookie, conn->sent_nonce, conn->sessionpublic_key, + conn->public_key) != sizeof(handshake_packet)) + return -1; + + if (new_temp_packet(c, crypt_connection_id, handshake_packet, sizeof(handshake_packet)) != 0) + return -1; + + send_temp_packet(c, crypt_connection_id); + } + conn->status = CRYPTO_CONN_NOT_CONFIRMED; } else { return -1; From 8ae0a79305973ccbd6220cf64a4270f75ac4daf5 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 2 May 2014 15:59:13 -0400 Subject: [PATCH 049/117] Move the handshake creating code to a function. Fixed another instance where it was not sent. --- toxcore/Messenger.c | 2 +- toxcore/net_crypto.c | 67 ++++++++++++++++++++++---------------------- 2 files changed, 35 insertions(+), 34 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 1a5c93aa..7fdae8f0 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -1738,7 +1738,7 @@ static void LANdiscovery(Messenger *m) } } -int handle_new_connections(void *object, New_Connection *n_c) +static int handle_new_connections(void *object, New_Connection *n_c) { Messenger *m = object; int friend_id = getfriend_id(m, n_c->public_key); diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index d71ccdda..a0a913d2 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -506,6 +506,32 @@ static int send_temp_packet(Net_Crypto *c, int crypt_connection_id) return 0; } +/* Create a handshake packet and set it as a temp packet. + * cookie must be COOKIE_LENGTH. + * + * return -1 on failure. + * return 0 on success. + */ +static int create_send_handshake(Net_Crypto *c, int crypt_connection_id, uint8_t *cookie) +{ + Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); + + if (conn == 0) + return -1; + + uint8_t handshake_packet[HANDSHAKE_PACKET_LENGTH]; + + if (create_crypto_handshake(c, handshake_packet, cookie, conn->sent_nonce, conn->sessionpublic_key, + conn->public_key) != sizeof(handshake_packet)) + return -1; + + if (new_temp_packet(c, crypt_connection_id, handshake_packet, sizeof(handshake_packet)) != 0) + return -1; + + send_temp_packet(c, crypt_connection_id); + return 0; +} + /* Handle a packet that was recieved for the connection. * * return -1 on failure. @@ -535,16 +561,9 @@ static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, uint if (number != conn->cookie_request_number) return -1; - uint8_t handshake_packet[HANDSHAKE_PACKET_LENGTH]; - - if (create_crypto_handshake(c, handshake_packet, cookie, conn->sent_nonce, conn->sessionpublic_key, - conn->public_key) != sizeof(handshake_packet)) + if (create_send_handshake(c, crypt_connection_id, cookie) != 0) return -1; - if (new_temp_packet(c, crypt_connection_id, handshake_packet, sizeof(handshake_packet)) != 0) - return -1; - - send_temp_packet(c, crypt_connection_id); conn->status = CRYPTO_CONN_HANDSHAKE_SENT; return 0; } @@ -561,16 +580,8 @@ static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, uint encrypt_precompute(conn->peersessionpublic_key, conn->sessionsecret_key, conn->shared_key); if (conn->status == CRYPTO_CONN_COOKIE_REQUESTING) { - uint8_t handshake_packet[HANDSHAKE_PACKET_LENGTH]; - - if (create_crypto_handshake(c, handshake_packet, cookie, conn->sent_nonce, conn->sessionpublic_key, - conn->public_key) != sizeof(handshake_packet)) + if (create_send_handshake(c, crypt_connection_id, cookie) != 0) return -1; - - if (new_temp_packet(c, crypt_connection_id, handshake_packet, sizeof(handshake_packet)) != 0) - return -1; - - send_temp_packet(c, crypt_connection_id); } conn->status = CRYPTO_CONN_NOT_CONFIRMED; @@ -761,9 +772,12 @@ static int handle_new_connection_handshake(Net_Crypto *c, IP_Port source, uint8_ memcpy(conn->peersessionpublic_key, n_c.peersessionpublic_key, crypto_box_PUBLICKEYBYTES); encrypt_precompute(conn->peersessionpublic_key, conn->sessionsecret_key, conn->shared_key); - conn->status = CRYPTO_CONN_NOT_CONFIRMED; crypto_connection_add_source(c, crypt_connection_id, source); - ret = 0; + + if (create_send_handshake(c, crypt_connection_id, n_c.cookie) == 0) { + conn->status = CRYPTO_CONN_NOT_CONFIRMED; + ret = 0; + } } free(n_c.cookie); @@ -805,13 +819,7 @@ int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c) if (n_c->cookie_length != COOKIE_LENGTH) return -1; - uint8_t handshake_packet[HANDSHAKE_PACKET_LENGTH]; - - if (create_crypto_handshake(c, handshake_packet, n_c->cookie, conn->sent_nonce, conn->sessionpublic_key, - conn->public_key) != sizeof(handshake_packet)) - return -1; - - if (new_temp_packet(c, crypt_connection_id, handshake_packet, sizeof(handshake_packet)) != 0) + if (create_send_handshake(c, crypt_connection_id, n_c->cookie) != 0) return -1; send_temp_packet(c, crypt_connection_id); @@ -1058,12 +1066,6 @@ void load_keys(Net_Crypto *c, uint8_t *keys) memcpy(c->self_secret_key, keys + crypto_box_PUBLICKEYBYTES, crypto_box_SECRETKEYBYTES); } -/* Handle received packets for not yet established crypto connections. */ -static void receive_crypto(Net_Crypto *c) -{ - -} - /* Run this to (re)initialize net_crypto. * Sets all the global connection variables to their default values. */ @@ -1105,7 +1107,6 @@ void do_net_crypto(Net_Crypto *c) { unix_time_update(); kill_timedout(c); - receive_crypto(c); send_crypto_packets(c); } From db78c99ff45a99ac0a5944317b679b5139e3a2c0 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 2 May 2014 21:25:23 -0400 Subject: [PATCH 050/117] Messenger now works with the new net_crypto api. Added callbacks in net_crypto for the data packets and status changes. Added onion_getfriend_DHT_pubkey to onion_client. Net crypto isn't done yet so connections between toxes are not lossless, this means file sending is broken hence why the test fails. --- toxcore/Messenger.c | 604 ++++++++++++++++++++++------------------- toxcore/net_crypto.c | 141 ++++++++-- toxcore/net_crypto.h | 76 +++++- toxcore/onion_client.c | 31 ++- toxcore/onion_client.h | 7 + 5 files changed, 526 insertions(+), 333 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 7fdae8f0..9889d666 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -1857,12 +1857,307 @@ static void check_friend_request_timed_out(Messenger *m, uint32_t i, uint64_t t) } } +static int handle_status(void *object, int i, uint8_t status) +{ + uint64_t temp_time = unix_time(); + Messenger *m = object; + + if (status) { /* Went online. */ + set_friend_status(m, i, FRIEND_ONLINE); + m->friendlist[i].name_sent = 0; + m->friendlist[i].userstatus_sent = 0; + m->friendlist[i].statusmessage_sent = 0; + m->friendlist[i].ping_lastrecv = temp_time; + } else { /* Went offline. */ + m->friendlist[i].crypt_connection_id = -1; + + if (m->friendlist[i].status == FRIEND_ONLINE) { + set_friend_status(m, i, FRIEND_CONFIRMED); + } + } + + return 0; +} + +static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len) +{ + if (len == 0) + return -1; + + Messenger *m = object; + uint64_t temp_time = unix_time(); + uint8_t packet_id = temp[0]; + uint8_t *data = temp + 1; + uint32_t data_length = len - 1; + + if (m->friendlist[i].status != FRIEND_ONLINE) + return -1; + + switch (packet_id) { + case PACKET_ID_ALIVE: { + m->friendlist[i].ping_lastrecv = temp_time; + break; + } + + case PACKET_ID_NICKNAME: { + if (data_length > MAX_NAME_LENGTH || data_length == 0) + break; + + /* Make sure the NULL terminator is present. */ + uint8_t data_terminated[data_length + 1]; + memcpy(data_terminated, data, data_length); + data_terminated[data_length] = 0; + + /* inform of namechange before we overwrite the old name */ + if (m->friend_namechange) + m->friend_namechange(m, i, data_terminated, data_length, m->friend_namechange_userdata); + + memcpy(m->friendlist[i].name, data_terminated, data_length); + m->friendlist[i].name_length = data_length; + + break; + } + + case PACKET_ID_STATUSMESSAGE: { + if (data_length == 0 || data_length > MAX_STATUSMESSAGE_LENGTH) + break; + + /* Make sure the NULL terminator is present. */ + uint8_t data_terminated[data_length + 1]; + memcpy(data_terminated, data, data_length); + data_terminated[data_length] = 0; + + if (m->friend_statusmessagechange) + m->friend_statusmessagechange(m, i, data_terminated, data_length, + m->friend_statuschange_userdata); + + set_friend_statusmessage(m, i, data_terminated, data_length); + break; + } + + case PACKET_ID_USERSTATUS: { + if (data_length != 1) + break; + + USERSTATUS status = data[0]; + + if (status >= USERSTATUS_INVALID) + break; + + if (m->friend_userstatuschange) + m->friend_userstatuschange(m, i, status, m->friend_userstatuschange_userdata); + + set_friend_userstatus(m, i, status); + break; + } + + case PACKET_ID_TYPING: { + if (data_length != 1) + break; + + uint8_t typing = data[0]; + + set_friend_typing(m, i, typing); + + if (m->friend_typingchange) + m->friend_typingchange(m, i, typing, m->friend_typingchange_userdata); + + break; + } + + case PACKET_ID_MESSAGE: { + uint8_t *message_id = data; + uint8_t message_id_length = 4; + + if (data_length <= message_id_length) + break; + + uint8_t *message = data + message_id_length; + uint16_t message_length = data_length - message_id_length; + + /* Make sure the NULL terminator is present. */ + uint8_t message_terminated[message_length + 1]; + memcpy(message_terminated, message, message_length); + message_terminated[message_length] = 0; + + if (m->friendlist[i].receives_read_receipts) { + write_cryptpacket_id(m, i, PACKET_ID_RECEIPT, message_id, message_id_length); + } + + if (m->friend_message) + (*m->friend_message)(m, i, message_terminated, message_length, m->friend_message_userdata); + + break; + } + + case PACKET_ID_ACTION: { + uint8_t *message_id = data; + uint8_t message_id_length = 4; + + if (data_length <= message_id_length) + break; + + uint8_t *action = data + message_id_length; + uint16_t action_length = data_length - message_id_length; + + /* Make sure the NULL terminator is present. */ + uint8_t action_terminated[action_length + 1]; + memcpy(action_terminated, action, action_length); + action_terminated[action_length] = 0; + + if (m->friendlist[i].receives_read_receipts) { + write_cryptpacket_id(m, i, PACKET_ID_RECEIPT, message_id, message_id_length); + } + + if (m->friend_action) + (*m->friend_action)(m, i, action_terminated, action_length, m->friend_action_userdata); + + break; + } + + case PACKET_ID_RECEIPT: { + uint32_t msgid; + + if (data_length < sizeof(msgid)) + break; + + memcpy(&msgid, data, sizeof(msgid)); + msgid = ntohl(msgid); + + if (m->read_receipt) + (*m->read_receipt)(m, i, msgid, m->read_receipt_userdata); + + break; + } + + case PACKET_ID_INVITE_GROUPCHAT: { + if (data_length != crypto_box_PUBLICKEYBYTES) + break; + + if (m->group_invite) + (*m->group_invite)(m, i, data, m->group_invite_userdata); + + break; + } + + case PACKET_ID_JOIN_GROUPCHAT: { + if (data_length != crypto_box_PUBLICKEYBYTES * 2) + break; + + int groupnum = group_num(m, data); + + if (groupnum == -1) + break; + + if (!group_invited(m, i, groupnum)) + break; + + group_newpeer(m->chats[groupnum], data + crypto_box_PUBLICKEYBYTES); + /* This is just there to speedup joining. */ + chat_bootstrap(m->chats[groupnum], get_friend_ipport(m, i), data + crypto_box_PUBLICKEYBYTES); + break; + } + + case PACKET_ID_FILE_SENDREQUEST: { + if (data_length < 1 + sizeof(uint64_t) + 1) + break; + + uint8_t filenumber = data[0]; + uint64_t filesize; + net_to_host(data + 1, sizeof(filesize)); + memcpy(&filesize, data + 1, sizeof(filesize)); + m->friendlist[i].file_receiving[filenumber].status = FILESTATUS_NOT_ACCEPTED; + m->friendlist[i].file_receiving[filenumber].size = filesize; + m->friendlist[i].file_receiving[filenumber].transferred = 0; + + /* Force NULL terminate file name. */ + uint8_t filename_terminated[data_length - 1 - sizeof(uint64_t) + 1]; + memcpy(filename_terminated, data + 1 + sizeof(uint64_t), data_length - 1 - sizeof(uint64_t)); + filename_terminated[data_length - 1 - sizeof(uint64_t)] = 0; + + if (m->file_sendrequest) + (*m->file_sendrequest)(m, i, filenumber, filesize, filename_terminated, data_length - 1 - sizeof(uint64_t), + m->file_sendrequest_userdata); + + break; + } + + case PACKET_ID_FILE_CONTROL: { + if (data_length < 3) + break; + + uint8_t send_receive = data[0]; + uint8_t filenumber = data[1]; + uint8_t control_type = data[2]; + + if (handle_filecontrol(m, i, send_receive, filenumber, control_type, data + 3, data_length - 3) == -1) + break; + + if (m->file_filecontrol) + (*m->file_filecontrol)(m, i, send_receive, filenumber, control_type, data + 3, data_length - 3, + m->file_filecontrol_userdata); + + break; + } + + case PACKET_ID_FILE_DATA: { + if (data_length < 2) + break; + + uint8_t filenumber = data[0]; + + if (m->friendlist[i].file_receiving[filenumber].status == FILESTATUS_NONE) + break; + + m->friendlist[i].file_receiving[filenumber].transferred += (data_length - 1); + + if (m->file_filedata) + (*m->file_filedata)(m, i, filenumber, data + 1, data_length - 1, m->file_filedata_userdata); + + break; + } + + case PACKET_ID_MSI: { + if (data_length == 0) + break; + + if (m->msi_packet) + (*m->msi_packet)(m, i, data, data_length, m->msi_packet_userdata); + } + + default: { + break; + } + } + + return 0; +} + +static int friend_new_connection(Messenger *m, int32_t friendnumber, uint8_t *real_public_key) +{ + if (friend_not_valid(m, friendnumber)) + return -1; + + if (m->friendlist[friendnumber].crypt_connection_id != -1) { + return -1; + } + + int id = new_crypto_connection(m->net_crypto, real_public_key); + + if (id == -1) + return -1; + + m->friendlist[friendnumber].crypt_connection_id = id; + connection_status_handler(m->net_crypto, id, &handle_status, m, friendnumber); + connection_data_handler(m->net_crypto, id, &handle_packet, m, friendnumber); + return 0; + +} + /* TODO: Make this function not suck. */ void do_friends(Messenger *m) { uint32_t i; - int len; - uint8_t temp[MAX_CRYPTO_DATA_SIZE]; uint64_t temp_time = unix_time(); for (i = 0; i < m->numfriends; ++i) { @@ -1886,35 +2181,21 @@ void do_friends(Messenger *m) check_friend_request_timed_out(m, i, temp_time); } + friend_new_connection(m, i, m->friendlist[i].client_id); + uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; + + if (onion_getfriend_DHT_pubkey(m->onion_c, m->friendlist[i].onion_friendnum, dht_public_key) == 0) { + set_conection_dht_public_key(m->net_crypto, m->friendlist[i].crypt_connection_id, dht_public_key); + } + IP_Port 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: - if (friendok == 1) - m->friendlist[i].crypt_connection_id = crypto_connect(m->net_crypto, m->friendlist[i].client_id, friendip); - - break; - - case CRYPTO_CONN_ESTABLISHED: /* Connection is established. */ - set_friend_status(m, i, FRIEND_ONLINE); - m->friendlist[i].name_sent = 0; - m->friendlist[i].userstatus_sent = 0; - m->friendlist[i].statusmessage_sent = 0; - m->friendlist[i].ping_lastrecv = temp_time; - break; - - case CRYPTO_CONN_TIMED_OUT: - crypto_kill(m->net_crypto, m->friendlist[i].crypt_connection_id); - m->friendlist[i].crypt_connection_id = -1; - break; - - default: - break; + if (onion_getfriendip(m->onion_c, m->friendlist[i].onion_friendnum, &friendip) == 1) { + set_direct_ip_port(m->net_crypto, m->friendlist[i].crypt_connection_id, friendip); } } - while (m->friendlist[i].status == FRIEND_ONLINE) { /* friend is online. */ + if (m->friendlist[i].status == FRIEND_ONLINE) { /* friend is online. */ if (m->friendlist[i].name_sent == 0) { if (m_sendname(m, i, m->name, m->name_length)) m->friendlist[i].name_sent = 1; @@ -1939,265 +2220,18 @@ void do_friends(Messenger *m) send_ping(m, i); } - len = read_cryptpacket(m->net_crypto, m->friendlist[i].crypt_connection_id, temp); - - if (len > 0) { - uint8_t packet_id = temp[0]; - uint8_t *data = temp + 1; - uint32_t data_length = len - 1; - - switch (packet_id) { - case PACKET_ID_ALIVE: { - m->friendlist[i].ping_lastrecv = temp_time; - break; - } - - case PACKET_ID_NICKNAME: { - if (data_length > MAX_NAME_LENGTH || data_length == 0) - break; - - /* Make sure the NULL terminator is present. */ - uint8_t data_terminated[data_length + 1]; - memcpy(data_terminated, data, data_length); - data_terminated[data_length] = 0; - - /* inform of namechange before we overwrite the old name */ - if (m->friend_namechange) - m->friend_namechange(m, i, data_terminated, data_length, m->friend_namechange_userdata); - - memcpy(m->friendlist[i].name, data_terminated, data_length); - m->friendlist[i].name_length = data_length; - - break; - } - - case PACKET_ID_STATUSMESSAGE: { - if (data_length == 0 || data_length > MAX_STATUSMESSAGE_LENGTH) - break; - - /* Make sure the NULL terminator is present. */ - uint8_t data_terminated[data_length + 1]; - memcpy(data_terminated, data, data_length); - data_terminated[data_length] = 0; - - if (m->friend_statusmessagechange) - m->friend_statusmessagechange(m, i, data_terminated, data_length, - m->friend_statuschange_userdata); - - set_friend_statusmessage(m, i, data_terminated, data_length); - break; - } - - case PACKET_ID_USERSTATUS: { - if (data_length != 1) - break; - - USERSTATUS status = data[0]; - - if (status >= USERSTATUS_INVALID) - break; - - if (m->friend_userstatuschange) - m->friend_userstatuschange(m, i, status, m->friend_userstatuschange_userdata); - - set_friend_userstatus(m, i, status); - break; - } - - case PACKET_ID_TYPING: { - if (data_length != 1) - break; - - uint8_t typing = data[0]; - - set_friend_typing(m, i, typing); - - if (m->friend_typingchange) - m->friend_typingchange(m, i, typing, m->friend_typingchange_userdata); - - break; - } - - case PACKET_ID_MESSAGE: { - uint8_t *message_id = data; - uint8_t message_id_length = 4; - - if (data_length <= message_id_length) - break; - - uint8_t *message = data + message_id_length; - uint16_t message_length = data_length - message_id_length; - - /* Make sure the NULL terminator is present. */ - uint8_t message_terminated[message_length + 1]; - memcpy(message_terminated, message, message_length); - message_terminated[message_length] = 0; - - if (m->friendlist[i].receives_read_receipts) { - write_cryptpacket_id(m, i, PACKET_ID_RECEIPT, message_id, message_id_length); - } - - if (m->friend_message) - (*m->friend_message)(m, i, message_terminated, message_length, m->friend_message_userdata); - - break; - } - - case PACKET_ID_ACTION: { - uint8_t *message_id = data; - uint8_t message_id_length = 4; - - if (data_length <= message_id_length) - break; - - uint8_t *action = data + message_id_length; - uint16_t action_length = data_length - message_id_length; - - /* Make sure the NULL terminator is present. */ - uint8_t action_terminated[action_length + 1]; - memcpy(action_terminated, action, action_length); - action_terminated[action_length] = 0; - - if (m->friendlist[i].receives_read_receipts) { - write_cryptpacket_id(m, i, PACKET_ID_RECEIPT, message_id, message_id_length); - } - - if (m->friend_action) - (*m->friend_action)(m, i, action_terminated, action_length, m->friend_action_userdata); - - break; - } - - case PACKET_ID_RECEIPT: { - uint32_t msgid; - - if (data_length < sizeof(msgid)) - break; - - memcpy(&msgid, data, sizeof(msgid)); - msgid = ntohl(msgid); - - if (m->read_receipt) - (*m->read_receipt)(m, i, msgid, m->read_receipt_userdata); - - break; - } - - case PACKET_ID_INVITE_GROUPCHAT: { - if (data_length != crypto_box_PUBLICKEYBYTES) - break; - - if (m->group_invite) - (*m->group_invite)(m, i, data, m->group_invite_userdata); - - break; - } - - case PACKET_ID_JOIN_GROUPCHAT: { - if (data_length != crypto_box_PUBLICKEYBYTES * 2) - break; - - int groupnum = group_num(m, data); - - if (groupnum == -1) - break; - - if (!group_invited(m, i, groupnum)) - break; - - group_newpeer(m->chats[groupnum], data + crypto_box_PUBLICKEYBYTES); - /* This is just there to speedup joining. */ - chat_bootstrap(m->chats[groupnum], get_friend_ipport(m, i), data + crypto_box_PUBLICKEYBYTES); - break; - } - - case PACKET_ID_FILE_SENDREQUEST: { - if (data_length < 1 + sizeof(uint64_t) + 1) - break; - - uint8_t filenumber = data[0]; - uint64_t filesize; - net_to_host(data + 1, sizeof(filesize)); - memcpy(&filesize, data + 1, sizeof(filesize)); - m->friendlist[i].file_receiving[filenumber].status = FILESTATUS_NOT_ACCEPTED; - m->friendlist[i].file_receiving[filenumber].size = filesize; - m->friendlist[i].file_receiving[filenumber].transferred = 0; - - /* Force NULL terminate file name. */ - uint8_t filename_terminated[data_length - 1 - sizeof(uint64_t) + 1]; - memcpy(filename_terminated, data + 1 + sizeof(uint64_t), data_length - 1 - sizeof(uint64_t)); - filename_terminated[data_length - 1 - sizeof(uint64_t)] = 0; - - if (m->file_sendrequest) - (*m->file_sendrequest)(m, i, filenumber, filesize, filename_terminated, data_length - 1 - sizeof(uint64_t), - m->file_sendrequest_userdata); - - break; - } - - case PACKET_ID_FILE_CONTROL: { - if (data_length < 3) - break; - - uint8_t send_receive = data[0]; - uint8_t filenumber = data[1]; - uint8_t control_type = data[2]; - - if (handle_filecontrol(m, i, send_receive, filenumber, control_type, data + 3, data_length - 3) == -1) - break; - - if (m->file_filecontrol) - (*m->file_filecontrol)(m, i, send_receive, filenumber, control_type, data + 3, data_length - 3, - m->file_filecontrol_userdata); - - break; - } - - case PACKET_ID_FILE_DATA: { - if (data_length < 2) - break; - - uint8_t filenumber = data[0]; - - if (m->friendlist[i].file_receiving[filenumber].status == FILESTATUS_NONE) - break; - - m->friendlist[i].file_receiving[filenumber].transferred += (data_length - 1); - - if (m->file_filedata) - (*m->file_filedata)(m, i, filenumber, data + 1, data_length - 1, m->file_filedata_userdata); - - break; - } - - case PACKET_ID_MSI: { - if (data_length == 0) - break; - - if (m->msi_packet) - (*m->msi_packet)(m, i, data, data_length, m->msi_packet_userdata); - } - - default: { - break; - } - } - } else { - if (is_cryptoconnected(m->net_crypto, - m->friendlist[i].crypt_connection_id) == CRYPTO_CONN_TIMED_OUT) { /* If the connection timed out, kill it. */ - crypto_kill(m->net_crypto, m->friendlist[i].crypt_connection_id); - m->friendlist[i].crypt_connection_id = -1; - set_friend_status(m, i, FRIEND_CONFIRMED); - } - - if (m->friendlist[i].ping_lastrecv + FRIEND_CONNECTION_TIMEOUT < temp_time) { - /* If we stopped recieving ping packets, kill it. */ - crypto_kill(m->net_crypto, m->friendlist[i].crypt_connection_id); - m->friendlist[i].crypt_connection_id = -1; - set_friend_status(m, i, FRIEND_CONFIRMED); - } - - break; + if (is_cryptoconnected(m->net_crypto, + m->friendlist[i].crypt_connection_id) == CRYPTO_CONN_TIMED_OUT) { /* If the connection timed out, kill it. */ + crypto_kill(m->net_crypto, m->friendlist[i].crypt_connection_id); + m->friendlist[i].crypt_connection_id = -1; + set_friend_status(m, i, FRIEND_CONFIRMED); + } + + if (m->friendlist[i].ping_lastrecv + FRIEND_CONNECTION_TIMEOUT < temp_time) { + /* If we stopped recieving ping packets, kill it. */ + crypto_kill(m->net_crypto, m->friendlist[i].crypt_connection_id); + m->friendlist[i].crypt_connection_id = -1; + set_friend_status(m, i, FRIEND_CONFIRMED); } } } diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index a0a913d2..9425afba 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -379,6 +379,7 @@ static int send_data_packet(Net_Crypto *c, int crypt_connection_id, uint8_t *dat return -1; increment_nonce(conn->sent_nonce); + conn->last_data_packet_sent = current_time(); //TODO remove this. return send_packet_to(c, crypt_connection_id, packet, sizeof(packet)); } @@ -459,6 +460,7 @@ static int new_temp_packet(Net_Crypto *c, int crypt_connection_id, uint8_t *pack conn->temp_packet = temp_packet; conn->temp_packet_length = length; conn->temp_packet_sent_time = 0; + conn->temp_packet_num_sent = 0; return 0; } @@ -480,6 +482,7 @@ static int clear_temp_packet(Net_Crypto *c, int crypt_connection_id) conn->temp_packet = 0; conn->temp_packet_length = 0; conn->temp_packet_sent_time = 0; + conn->temp_packet_num_sent = 0; return 0; } @@ -503,6 +506,7 @@ static int send_temp_packet(Net_Crypto *c, int crypt_connection_id) return -1; conn->temp_packet_sent_time = current_time(); + ++conn->temp_packet_num_sent; return 0; } @@ -594,7 +598,24 @@ static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, uint case NET_PACKET_CRYPTO_DATA: { if (conn->status == CRYPTO_CONN_NOT_CONFIRMED || conn->status == CRYPTO_CONN_ESTABLISHED) { - //TODO + uint8_t data[MAX_DATA_DATA_PACKET_SIZE]; + int len = handle_data_packet(c, crypt_connection_id, data, packet, length); + + if (len == -1) + return -1; + + if (conn->status == CRYPTO_CONN_NOT_CONFIRMED) { + if (conn->connection_status_callback) + conn->connection_status_callback(conn->connection_status_callback_object, conn->connection_status_callback_id, 1); + + clear_temp_packet(c, crypt_connection_id); + conn->status = CRYPTO_CONN_ESTABLISHED; + } + + if (conn->connection_data_callback) + conn->connection_data_callback(conn->connection_data_callback_object, conn->connection_data_callback_id, data, len); + + //TODO add buffers and packet requesting. } else { return -1; } @@ -870,6 +891,9 @@ int set_conection_dht_public_key(Net_Crypto *c, int crypt_connection_id, uint8_t if (conn == 0) return -1; + if (conn->dht_public_key_set == 1 && memcmp(conn->dht_public_key, dht_public_key, crypto_box_PUBLICKEYBYTES) == 0) + return -1; + memcpy(conn->dht_public_key, dht_public_key, crypto_box_PUBLICKEYBYTES); conn->dht_public_key_set = 1; @@ -908,6 +932,52 @@ int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port) return 0; } +/* Set function to be called when connection with crypt_connection_id goes connects/disconnects. + * + * The set function should return -1 on failure and 0 on success. + * Note that if this function is set, the connection will clear itself on disconnect. + * Object and id will be passed to this function untouched. + * status is 1 if the connection is going online, 0 if it is going offline. + * + * return -1 on failure. + * return 0 on success. + */ +int connection_status_handler(Net_Crypto *c, int crypt_connection_id, int (*connection_status_callback)(void *object, + int id, uint8_t status), void *object, int id) +{ + Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); + + if (conn == 0) + return -1; + + conn->connection_status_callback = connection_status_callback; + conn->connection_status_callback_object = object; + conn->connection_status_callback_id = id; + return 0; +} + +/* Set function to be called when connection with crypt_connection_id receives a data packet of length. + * + * The set function should return -1 on failure and 0 on success. + * Object and id will be passed to this function untouched. + * + * return -1 on failure. + * return 0 on success. + */ +int connection_data_handler(Net_Crypto *c, int crypt_connection_id, int (*connection_data_callback)(void *object, + int id, uint8_t *data, uint16_t length), void *object, int id) +{ + Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); + + if (conn == 0) + return -1; + + conn->connection_data_callback = connection_data_callback; + conn->connection_data_callback_object = object; + conn->connection_data_callback_id = id; + return 0; +} + /* Get the crypto connection id from the ip_port. * * return -1 on failure. @@ -977,27 +1047,26 @@ static void send_crypto_packets(Net_Crypto *c) if (conn == 0) return; - if ((CRYPTO_SEND_PACKET_INTERVAL * 1000UL) + conn->temp_packet_sent_time < temp_time) { + if ((CRYPTO_SEND_PACKET_INTERVAL * 1000ULL) + conn->temp_packet_sent_time < temp_time) { send_temp_packet(c, i); } + + if (conn->status >= CRYPTO_CONN_NOT_CONFIRMED + && (500ULL * 1000ULL) + conn->last_data_packet_sent < temp_time) {//TODO remove this. + uint8_t data[4] = {}; + send_data_packet(c, i, data, 4); + } } } -/* return 0 if there is no received data in the buffer. - * return -1 if the packet was discarded. - * return length of received data if successful. - */ -int read_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data) -{ - -} /* returns the number of packet slots left in the sendbuffer. * return 0 if failure. */ uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id) { - + //TODO + return 0; } /* return 0 if data could not be put in packet queue. @@ -1005,28 +1074,22 @@ uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id) */ int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length) { + //TODO + if (send_data_packet(c, crypt_connection_id, data, length) == 0) + return 1; -} - - -/* Start a secure connection with other peer who has public_key and ip_port. - * - * return -1 if failure. - * return crypt_connection_id of the initialized connection if everything went well. - */ -int crypto_connect(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port) -{ - + return 0; } /* Kill a crypto connection. * - * return 0 if killed successfully. - * return 1 if there was a problem. + * return -1 on failure. + * return 0 on success. */ int crypto_kill(Net_Crypto *c, int crypt_connection_id) { - + //TODO + return wipe_crypto_connection(c, crypt_connection_id); } /* return 0 if no connection. @@ -1096,9 +1159,35 @@ Net_Crypto *new_net_crypto(DHT *dht) static void kill_timedout(Net_Crypto *c) { uint32_t i; + uint64_t temp_time = current_time(); for (i = 0; i < c->crypto_connections_length; ++i) { -//TODO + Crypto_Connection *conn = get_crypto_connection(c, i); + + if (conn == 0) + return; + + if (conn->status == CRYPTO_CONN_NO_CONNECTION || conn->status == CRYPTO_CONN_TIMED_OUT) + continue; + + if (conn->status == CRYPTO_CONN_COOKIE_REQUESTING || conn->status == CRYPTO_CONN_HANDSHAKE_SENT + || conn->status == CRYPTO_CONN_NOT_CONFIRMED) { + if (conn->temp_packet_num_sent < MAX_NUM_SENDPACKET_TRIES) + continue; + + if (conn->connection_status_callback) { + conn->connection_status_callback(conn->connection_status_callback_object, conn->connection_status_callback_id, 0); + crypto_kill(c, i); + continue; + } + + conn->status = CRYPTO_CONN_TIMED_OUT; + continue; + } + + if (conn->status == CRYPTO_CONN_ESTABLISHED) { + //TODO: add a timeout here? + } } } diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index 3d58e5c1..5d4ff35b 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -44,6 +44,9 @@ /* Interval in ms between sending cookie request/handshake packets. */ #define CRYPTO_SEND_PACKET_INTERVAL 500 +/* The maximum number of times we try to send the cookie request and handshake + before giving up. */ +#define MAX_NUM_SENDPACKET_TRIES 10 typedef struct { uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* The real public key of the peer. */ @@ -59,8 +62,6 @@ typedef struct { * 4 if the connection is established. * 5 if the connection is timed out. */ - uint64_t timeout; - uint64_t cookie_request_number; /* number used in the cookie request packets for this connection */ uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; /* The dht public key of the peer */ uint8_t dht_public_key_set; /* True if the dht public key is set, false if it isn't. */ @@ -68,9 +69,20 @@ typedef struct { uint8_t *temp_packet; /* Where the cookie request/handshake packet is stored while it is being sent. */ uint16_t temp_packet_length; uint64_t temp_packet_sent_time; /* The time at which the last temp_packet was sent in ms. */ + uint32_t temp_packet_num_sent; IP_Port ip_port; /* The ip and port to contact this guy directly.*/ uint64_t direct_lastrecv_time; /* The Time at which we last receive a direct packet. */ + + int (*connection_status_callback)(void *object, int id, uint8_t status); + void *connection_status_callback_object; + int connection_status_callback_id; + + int (*connection_data_callback)(void *object, int id, uint8_t *data, uint16_t length); + void *connection_data_callback_object; + int connection_data_callback_id; + + uint64_t last_data_packet_sent; } Crypto_Connection; typedef struct { @@ -117,12 +129,52 @@ void new_connection_handler(Net_Crypto *c, int (*new_connection_callback)(void * */ int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c); - -/* return 0 if there is no received data in the buffer. - * return -1 if the packet was discarded. - * return length of received data if successful. +/* Create a crypto connection. + * If one to that real public key already exists, return it. + * + * return -1 on failure. + * return connection id on success. */ -int read_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data); +int new_crypto_connection(Net_Crypto *c, uint8_t *real_public_key); + +/* Set the DHT public key of the crypto connection. + * + * return -1 on failure. + * return 0 on success. + */ +int set_conection_dht_public_key(Net_Crypto *c, int crypt_connection_id, uint8_t *dht_public_key); + +/* Set the direct ip of the crypto connection. + * + * return -1 on failure. + * return 0 on success. + */ +int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port); + +/* Set function to be called when connection with crypt_connection_id goes connects/disconnects. + * + * The set function should return -1 on failure and 0 on success. + * Note that if this function is set, the connection will clear itself on disconnect. + * Object and id will be passed to this function untouched. + * status is 1 if the connection is going online, 0 if it is going offline. + * + * return -1 on failure. + * return 0 on success. + */ +int connection_status_handler(Net_Crypto *c, int crypt_connection_id, int (*connection_status_callback)(void *object, + int id, uint8_t status), void *object, int id); + +/* Set function to be called when connection with crypt_connection_id receives a data packet of length. + * + * The set function should return -1 on failure and 0 on success. + * Object and id will be passed to this function untouched. + * + * return -1 on failure. + * return 0 on success. + */ +int connection_data_handler(Net_Crypto *c, int crypt_connection_id, int (*connection_data_callback)(void *object, + int id, uint8_t *data, uint16_t length), void *object, int id); + /* returns the number of packet slots left in the sendbuffer. * return 0 if failure. @@ -134,17 +186,11 @@ uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id) */ int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length); -/* Start a secure connection with other peer who has public_key and ip_port. - * - * return -1 if failure. - * return crypt_connection_id of the initialized connection if everything went well. - */ -int crypto_connect(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port); /* Kill a crypto connection. * - * return 0 if killed successfully. - * return 1 if there was a problem. + * return -1 on failure. + * return 0 on success. */ int crypto_kill(Net_Crypto *c, int crypt_connection_id); diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index c7ebcd15..ca92ee42 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c @@ -796,14 +796,12 @@ int onion_delfriend(Onion_Client *onion_c, int friend_num) return friend_num; } -/* Get the ip of friend friendnum and put it in ip_port - * - * 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 +/* Copy friends DHT public key into dht_key. * + * return -1 on failure (no key copied). + * return 0 on success (key copied). */ -int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port) +int onion_getfriend_DHT_pubkey(Onion_Client *onion_c, int friend_num, uint8_t *dht_key) { if ((uint32_t)friend_num >= onion_c->num_friends) return -1; @@ -814,9 +812,28 @@ int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port) if (!onion_c->friends_list[friend_num].is_fake_clientid) return -1; - return DHT_getfriendip(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id, ip_port); + memcpy(dht_key, onion_c->friends_list[friend_num].fake_client_id, crypto_box_PUBLICKEYBYTES); + return 0; } +/* Get the ip of friend friendnum and put it in ip_port + * + * 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) +{ + uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; + + if (onion_getfriend_DHT_pubkey(onion_c, friend_num, dht_public_key) != 0) + return -1; + + return DHT_getfriendip(onion_c->dht, dht_public_key, 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. * diff --git a/toxcore/onion_client.h b/toxcore/onion_client.h index 6b960e40..4affcc6a 100644 --- a/toxcore/onion_client.h +++ b/toxcore/onion_client.h @@ -172,6 +172,13 @@ int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_on */ int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port); +/* Copy friends DHT public key into dht_key. + * + * return -1 on failure (no key copied). + * return 0 on success (key copied). + */ +int onion_getfriend_DHT_pubkey(Onion_Client *onion_c, int friend_num, uint8_t *dht_key); + #define ONION_DATA_IN_RESPONSE_MIN_SIZE (crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES) #define ONION_CLIENT_MAX_DATA_SIZE (MAX_DATA_REQUEST_SIZE - ONION_DATA_IN_RESPONSE_MIN_SIZE) From 38ebfc298966c20943a212a83c2cb1bcb0d7765d Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 2 May 2014 21:44:09 -0400 Subject: [PATCH 051/117] Fixed one test. --- auto_tests/messenger_test.c | 5 ++--- toxcore/Messenger.c | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/auto_tests/messenger_test.c b/auto_tests/messenger_test.c index 76cbf663..7ab7d674 100644 --- a/auto_tests/messenger_test.c +++ b/auto_tests/messenger_test.c @@ -16,7 +16,6 @@ #include "../testing/misc_tools.c" // hex_string_to_bin #include "../toxcore/Messenger.h" -#include "../toxcore/Lossless_UDP.h" #include #include #include @@ -46,7 +45,7 @@ START_TEST(test_m_sendmesage) { char *message = "h-hi :3"; int good_len = strlen(message); - int bad_len = MAX_DATA_SIZE; + int bad_len = MAX_CRYPTO_PACKET_SIZE; ck_assert(m_sendmessage(m, -1, (uint8_t *)message, good_len) == 0); @@ -127,7 +126,7 @@ START_TEST(test_m_addfriend) int good_len = strlen(good_data); int bad_len = strlen(bad_data); - int really_bad_len = (MAX_DATA_SIZE - crypto_box_PUBLICKEYBYTES + int really_bad_len = (MAX_CRYPTO_PACKET_SIZE - crypto_box_PUBLICKEYBYTES - crypto_box_NONCEBYTES - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES + 100); */ /* TODO: Update this properly to latest master diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 9889d666..37feccf5 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -1832,8 +1832,8 @@ void kill_messenger(Messenger *m) 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_DHT(m->dht); kill_networking(m->net); free(m->friendlist); free(m); From 20e9d9c079e9b330296625dcfa5bfacd376d9ff0 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 2 May 2014 21:51:55 -0400 Subject: [PATCH 052/117] Fixed other test. --- auto_tests/crypto_test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/auto_tests/crypto_test.c b/auto_tests/crypto_test.c index 39893515..252f7275 100644 --- a/auto_tests/crypto_test.c +++ b/auto_tests/crypto_test.c @@ -209,11 +209,11 @@ START_TEST(test_large_data) unsigned char n[crypto_box_NONCEBYTES]; - unsigned char m1[MAX_DATA_SIZE - crypto_box_MACBYTES]; + unsigned char m1[MAX_CRYPTO_PACKET_SIZE - crypto_box_MACBYTES]; unsigned char c1[sizeof(m1) + crypto_box_MACBYTES]; unsigned char m1prime[sizeof(m1)]; - unsigned char m2[MAX_DATA_SIZE]; + unsigned char m2[MAX_CRYPTO_PACKET_SIZE]; unsigned char c2[sizeof(m2) + crypto_box_MACBYTES]; int c1len, c2len; From 4dc0af61c6ea5b1581aca0d15cfd9ffc0f525b10 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 3 May 2014 11:58:45 -0400 Subject: [PATCH 053/117] All time in core is now monotonic. --- toxcore/net_crypto.c | 16 +++++++-------- toxcore/net_crypto.h | 3 ++- toxcore/network.c | 46 +++++++++++++++++++++++++++++++++++++------- toxcore/network.h | 4 ++-- toxcore/util.c | 8 ++++++-- 5 files changed, 57 insertions(+), 20 deletions(-) diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 9425afba..d4922380 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -379,7 +379,7 @@ static int send_data_packet(Net_Crypto *c, int crypt_connection_id, uint8_t *dat return -1; increment_nonce(conn->sent_nonce); - conn->last_data_packet_sent = current_time(); //TODO remove this. + conn->last_data_packet_sent = current_time_monotonic(); //TODO remove this. return send_packet_to(c, crypt_connection_id, packet, sizeof(packet)); } @@ -505,7 +505,7 @@ static int send_temp_packet(Net_Crypto *c, int crypt_connection_id) if (send_packet_to(c, crypt_connection_id, conn->temp_packet, conn->temp_packet_length) != 0) return -1; - conn->temp_packet_sent_time = current_time(); + conn->temp_packet_sent_time = current_time_monotonic(); ++conn->temp_packet_num_sent; return 0; } @@ -738,7 +738,7 @@ static int crypto_connection_add_source(Net_Crypto *c, int crypt_connection_id, if (source.ip.family == AF_INET || source.ip.family == AF_INET6) { conn->ip_port = source; - conn->direct_lastrecv_time = current_time(); + conn->direct_lastrecv_time = current_time_monotonic(); return 0; } @@ -1032,14 +1032,14 @@ static int udp_handle_packet(void *object, IP_Port source, uint8_t *packet, uint if (conn == 0) return -1; - conn->direct_lastrecv_time = current_time(); + conn->direct_lastrecv_time = current_time_monotonic(); return 0; } static void send_crypto_packets(Net_Crypto *c) { uint32_t i; - uint64_t temp_time = current_time(); + uint64_t temp_time = current_time_monotonic(); for (i = 0; i < c->crypto_connections_length; ++i) { Crypto_Connection *conn = get_crypto_connection(c, i); @@ -1047,12 +1047,12 @@ static void send_crypto_packets(Net_Crypto *c) if (conn == 0) return; - if ((CRYPTO_SEND_PACKET_INTERVAL * 1000ULL) + conn->temp_packet_sent_time < temp_time) { + if (CRYPTO_SEND_PACKET_INTERVAL + conn->temp_packet_sent_time < temp_time) { send_temp_packet(c, i); } if (conn->status >= CRYPTO_CONN_NOT_CONFIRMED - && (500ULL * 1000ULL) + conn->last_data_packet_sent < temp_time) {//TODO remove this. + && (500ULL + conn->last_data_packet_sent) < temp_time) {//TODO remove this. uint8_t data[4] = {}; send_data_packet(c, i, data, 4); } @@ -1159,7 +1159,7 @@ Net_Crypto *new_net_crypto(DHT *dht) static void kill_timedout(Net_Crypto *c) { uint32_t i; - uint64_t temp_time = current_time(); + //uint64_t temp_time = current_time_monotonic(); for (i = 0; i < c->crypto_connections_length; ++i) { Crypto_Connection *conn = get_crypto_connection(c, i); diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index 5d4ff35b..0389f283 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -72,7 +72,8 @@ typedef struct { uint32_t temp_packet_num_sent; IP_Port ip_port; /* The ip and port to contact this guy directly.*/ - uint64_t direct_lastrecv_time; /* The Time at which we last receive a direct packet. */ + uint64_t direct_lastrecv_time; /* The Time at which we last received a direct packet in ms. */ + int (*connection_status_callback)(void *object, int id, uint8_t status); void *connection_status_callback_object; diff --git a/toxcore/network.c b/toxcore/network.c index 28925180..69874189 100644 --- a/toxcore/network.c +++ b/toxcore/network.c @@ -183,8 +183,9 @@ int set_socket_dualstack(sock_t sock) return (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6only, sizeof(ipv6only)) == 0); } + /* return current UNIX time in microseconds (us). */ -uint64_t current_time(void) +static uint64_t current_time_actual(void) { uint64_t time; #if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) @@ -205,6 +206,37 @@ uint64_t current_time(void) } +#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) +static uint64_t last_monotime; +static uint64_t add_monotime; +#endif + +/* return current monotonic time in milliseconds (ms). */ +uint64_t current_time_monotonic(void) +{ + uint64_t time; +#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) + time = (uint64_t)GetTickCount() + add_monotime; + + if (time < last_monotime) { /* Prevent time from ever decreasing because of 32 bit wrap. */ + uint32_t add = ~0; + add_monotime += add; + time += add; + } + + last_monotime = time; +#else + struct timespec monotime; +#if defined(__linux__) + clock_gettime(CLOCK_MONOTONIC_RAW, &monotime); +#else + clock_gettime(CLOCK_MONOTONIC, &monotime); +#endif + time = 1000ULL * monotime.tv_sec + (monotime.tv_nsec / 1000000ULL); +#endif + return time; +} + #ifdef LOGGING static void loglogdata(char *message, uint8_t *buffer, size_t buflen, IP_Port *ip_port, ssize_t res); #endif @@ -273,7 +305,7 @@ int sendpacket(Networking_Core *net, IP_Port ip_port, uint8_t *data, uint32_t le if ((res >= 0) && ((uint32_t)res == length)) net->send_fail_eagain = 0; else if ((res < 0) && (errno == EWOULDBLOCK)) - net->send_fail_eagain = current_time(); + net->send_fail_eagain = current_time_monotonic(); return res; } @@ -421,13 +453,13 @@ int networking_wait_execute(uint8_t *data, long seconds, long microseconds) * that code) */ if (s->send_fail_eagain != 0) { - // current_time(): microseconds - uint64_t now = current_time(); + // current_time(): milliseconds + uint64_t now = current_time_monotonic(); /* s->sendqueue_length: might be used to guess how long we keep checking */ /* for now, threshold is hardcoded to 250ms, too long for a really really * fast link, but too short for a sloooooow link... */ - if (now - s->send_fail_eagain < 250000) { + if (now - s->send_fail_eagain < 250) { writefds_add = 1; } } @@ -522,9 +554,9 @@ int networking_at_startup(void) return -1; #else - srandom((uint32_t)current_time()); + srandom((uint32_t)current_time_actual()); #endif - srand((uint32_t)current_time()); + srand((uint32_t)current_time_actual()); at_startup_ran = 1; return 0; } diff --git a/toxcore/network.h b/toxcore/network.h index 4a893cff..e268df74 100644 --- a/toxcore/network.h +++ b/toxcore/network.h @@ -322,8 +322,8 @@ int set_socket_nosigpipe(sock_t sock); */ int set_socket_dualstack(sock_t sock); -/* return current UNIX time in microseconds (us). */ -uint64_t current_time(void); +/* return current monotonic time in milliseconds (ms). */ +uint64_t current_time_monotonic(void); /* Basic network functions: */ diff --git a/toxcore/util.c b/toxcore/util.c index 07db57f0..58f0336c 100644 --- a/toxcore/util.c +++ b/toxcore/util.c @@ -36,10 +36,14 @@ /* don't call into system billions of times for no reason */ static uint64_t unix_time_value; +static uint64_t unix_base_time_value; void unix_time_update() { - unix_time_value = (uint64_t)time(NULL); + if (unix_base_time_value == 0) + unix_base_time_value = ((uint64_t)time(NULL) - (current_time_monotonic() / 1000ULL)); + + unix_time_value = (current_time_monotonic() / 1000ULL) + unix_base_time_value; } uint64_t unix_time() @@ -49,7 +53,7 @@ uint64_t unix_time() int is_timeout(uint64_t timestamp, uint64_t timeout) { - return timestamp + timeout <= unix_time_value; + return timestamp + timeout <= unix_time(); } From fca5e1b99aaa09f60c6f3f469fdfd23231f50c90 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sun, 4 May 2014 20:04:43 -0400 Subject: [PATCH 054/117] Added arrays to store packets on send/recv in net crypto. Wrote down more of the protocol. Padding support has been added and implemented which will make it possible for us to pad packets to mitigate length related attacks. --- docs/Tox_middle_level_network_protocol.txt | 31 ++- toxcore/Messenger.c | 2 +- toxcore/net_crypto.c | 309 +++++++++++++++++++-- toxcore/net_crypto.h | 34 ++- 4 files changed, 334 insertions(+), 42 deletions(-) diff --git a/docs/Tox_middle_level_network_protocol.txt b/docs/Tox_middle_level_network_protocol.txt index 7b65db51..f9b03196 100644 --- a/docs/Tox_middle_level_network_protocol.txt +++ b/docs/Tox_middle_level_network_protocol.txt @@ -41,8 +41,8 @@ Detailed implementation details: cookie request packet: [uint8_t 24][Senders DHT Public key (32 bytes)][Random nonce (24 bytes)][Encrypted message containing: [Senders real public key (32 -bytes)][Recievers real public key (32 bytes)][uint64_t number (must be sent back -untouched in cookie response)]] +bytes)][Recievers real public key (32 bytes)][uint64_t number (must be sent +back untouched in cookie response)]] Encrypted message is encrypted with sender DHT private key, recievers DHT public key and the nonce. @@ -88,9 +88,30 @@ in the handshake will be used to encrypt the first data packet sent, the nonce Data packets: -[uint8_t 27][uint16_t (in network byte order) the last 2 bytes of the nonce used -to encrypt this][encrypted with the session key and a nonce:[data]] +[uint8_t 27][uint16_t (in network byte order) the last 2 bytes of the nonce +used to encrypt this][encrypted with the session key and a nonce:[plain data]] -Data in the data packets: +Plain data in the data packets: + +[uint32_t our recvbuffers buffer_start, (highest packet number handled + +1)][uint32_t packet number if lossless, our sendbuffer buffer_end if +lossy][data] + +data ids: +0: padding (skipped until we hit a non zero (data id) byte) +1: packet request packet (lossy packet) ... +16+: reserved for Messenger usage (lossless packets). + +packet request packet: [uint8_t (1)][uint8_t num][uint8_t num][uint8_t +num]...[uint8_t num] + +the list of nums are a list of packet numbers the other is requesting. +to get the real packet numbers from this list take the recvbuffers buffer_start +from the packet, substract 1 to it and put it in packet_num then start from the +beggining of the num list: if num is zero, add 255 to packet_num then do the +next num. if num isn't zero, add its value to packet_num, note that the other +has requested we send this packet again to them then continue to the next num in +the list. + diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 37feccf5..a84c391b 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -849,7 +849,7 @@ int write_cryptpacket_id(Messenger *m, int32_t friendnumber, uint8_t packet_id, if (length != 0) memcpy(packet + 1, data, length); - return write_cryptpacket(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id, packet, length + 1); + return write_cryptpacket(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id, packet, length + 1) != -1; } /**********GROUP CHATS************/ diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index d4922380..9f8048be 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -358,6 +358,138 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, uint8_t *data, return 0; } +/** START: Array Related functions **/ + + +/* Return number of packets in array + * Note that holes are counted too. + */ +static uint32_t num_packets_array(Packets_Array *array) +{ + return array->buffer_end - array->buffer_start; +} + +/* Add data with packet number to array. + * + * return -1 on failure. + * return 0 on success. + */ +static int add_data_to_buffer(Packets_Array *array, uint32_t number, Packet_Data *data) +{ + if (number - array->buffer_start > CRYPTO_PACKET_BUFFER_SIZE) + return -1; + + uint32_t num = number % CRYPTO_PACKET_BUFFER_SIZE; + + if (array->buffer[num]) + return -1; + + Packet_Data *new_d = malloc(sizeof(Packet_Data)); + + if (new_d == NULL) + return -1; + + memcpy(new_d, data, sizeof(Packet_Data)); + array->buffer[num] = new_d; + + if ((number - array->buffer_start) >= (array->buffer_end - array->buffer_start)) + array->buffer_end = number + 1; + + return 0; +} + +/* Copy data with packet number to data. + * + * return -1 on failure. + * return 0 on success. + */ +static int copy_data_number(Packets_Array *array, Packet_Data *data, uint32_t number) +{ + uint32_t num_spots = array->buffer_end - array->buffer_start; + + if (array->buffer_end - number > num_spots || number - array->buffer_start >= num_spots) + return -1; + + uint32_t num = number % CRYPTO_PACKET_BUFFER_SIZE; + + if (!array->buffer[num]) + return -1; + + memcpy(data, array->buffer[num], sizeof(Packet_Data)); + return 0; +} + +/* Add data to end of array. + * + * return -1 on failure. + * return packet number on success. + */ +static int64_t add_data_end_of_buffer(Packets_Array *array, Packet_Data *data) +{ + if (num_packets_array(array) >= CRYPTO_PACKET_BUFFER_SIZE) + return -1; + + Packet_Data *new_d = malloc(sizeof(Packet_Data)); + + if (new_d == NULL) + return -1; + + memcpy(new_d, data, sizeof(Packet_Data)); + uint32_t id = array->buffer_end; + array->buffer[id % CRYPTO_PACKET_BUFFER_SIZE] = new_d; + ++array->buffer_end; + return id; +} + +/* Read data from begginning of array. + * + * return -1 on failure. + * return packet number on success. + */ +static int64_t read_data_beg_buffer(Packets_Array *array, Packet_Data *data) +{ + if (array->buffer_end == array->buffer_start) + return -1; + + uint32_t num = array->buffer_start % CRYPTO_PACKET_BUFFER_SIZE; + + if (!array->buffer[num]) + return -1; + + memcpy(data, array->buffer[num], sizeof(Packet_Data)); + uint32_t id = array->buffer_start; + ++array->buffer_start; + return id; +} + +/* Delete all packets in array before number (but not number) + * + * return -1 on failure. + * return 0 on success + */ +static int clear_buffer_until(Packets_Array *array, uint32_t number) +{ + uint32_t num_spots = array->buffer_end - array->buffer_start; + + if (array->buffer_end - number >= num_spots || number - array->buffer_start > num_spots) + return -1; + + uint32_t i; + + for (i = array->buffer_start; i != number; ++i) { + uint32_t num = i % CRYPTO_PACKET_BUFFER_SIZE; + + if (array->buffer[num]) { + free(array->buffer[num]); + array->buffer[num] = NULL; + } + } + + array->buffer_start = i; + return 0; +} +/** END: Array Related functions **/ + #define MAX_DATA_DATA_PACKET_SIZE (MAX_CRYPTO_PACKET_SIZE - (1 + sizeof(uint16_t) + crypto_box_MACBYTES)) static int send_data_packet(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint16_t length) @@ -383,6 +515,47 @@ static int send_data_packet(Net_Crypto *c, int crypt_connection_id, uint8_t *dat return send_packet_to(c, crypt_connection_id, packet, sizeof(packet)); } +static int send_data_packet_helper(Net_Crypto *c, int crypt_connection_id, uint32_t buffer_start, uint32_t num, + uint8_t *data, uint32_t length) +{ + num = htonl(num); + buffer_start = htonl(buffer_start); + uint8_t packet[sizeof(uint32_t) + sizeof(uint32_t) + length]; + memcpy(packet, &buffer_start, sizeof(uint32_t)); + memcpy(packet + sizeof(uint32_t), &num, sizeof(uint32_t)); + memcpy(packet + (sizeof(uint32_t) * 2), data, length); + + return send_data_packet(c, crypt_connection_id, packet, sizeof(packet)); +} + +/* return -1 if data could not be put in packet queue. + * return positive packet number if data was put into the queue. + */ +static int64_t send_lossless_packet(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length) +{ + if (length == 0 || length > MAX_CRYPTO_DATA_SIZE) + return -1; + + Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); + + if (conn == 0) + return -1; + + Packet_Data dt; + dt.time = current_time_monotonic(); + dt.length = length; + memcpy(dt.data, data, length); + int64_t packet_num = add_data_end_of_buffer(&conn->send_array, &dt); + + if (packet_num == -1) + return -1; + + if (send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, packet_num, data, length) != 0) + printf("send_data_packet failed\n"); + + return packet_num; +} + /* Get the lowest 2 bytes from the nonce and convert * them to host byte format before returning them. */ @@ -433,6 +606,7 @@ static int handle_data_packet(Net_Crypto *c, int crypt_connection_id, uint8_t *d return len; } + /* Add a new temp packet to send repeatedly. * * return -1 on failure. @@ -536,6 +710,80 @@ static int create_send_handshake(Net_Crypto *c, int crypt_connection_id, uint8_t return 0; } +/* Handle a recieved data packet. + * + * return -1 on failure. + * return 0 on success. + */ +static int handle_data_packet_helper(Net_Crypto *c, int crypt_connection_id, uint8_t *packet, uint16_t length) +{ + if (length > MAX_CRYPTO_PACKET_SIZE || length <= CRYPTO_DATA_PACKET_MIN_SIZE) + return -1; + + Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); + + if (conn == 0) + return -1; + + uint8_t data[MAX_DATA_DATA_PACKET_SIZE]; + int len = handle_data_packet(c, crypt_connection_id, data, packet, length); + + if (len <= (int)(sizeof(uint32_t) * 2)) + return -1; + + uint32_t buffer_start, num; + memcpy(&buffer_start, data, sizeof(uint32_t)); + memcpy(&num, data + sizeof(uint32_t), sizeof(uint32_t)); + buffer_start = ntohl(buffer_start); + num = ntohl(num); + + if (buffer_start != conn->send_array.buffer_start && clear_buffer_until(&conn->send_array, buffer_start) != 0) + return -1; + + uint8_t *real_data = data + (sizeof(uint32_t) * 2); + uint16_t real_length = len - (sizeof(uint32_t) * 2); + + while (real_data[0] == 0) { /* Remove Padding */ + ++real_data; + --real_length; + + if (real_length == 0) + return -1; + } + + if (real_data[0] == PACKET_ID_REQUEST) { + if (real_length <= 1) + return -1; + + + //TODO + } else { + Packet_Data dt; + dt.time = current_time_monotonic(); + dt.length = real_length; + memcpy(dt.data, real_data, real_length); + + if (add_data_to_buffer(&conn->recv_array, num, &dt) != 0) + return -1; + + while (read_data_beg_buffer(&conn->recv_array, &dt) != -1) { + if (conn->connection_data_callback) + conn->connection_data_callback(conn->connection_data_callback_object, conn->connection_data_callback_id, dt.data, + dt.length); + } + } + + if (conn->status == CRYPTO_CONN_NOT_CONFIRMED) { + if (conn->connection_status_callback) + conn->connection_status_callback(conn->connection_status_callback_object, conn->connection_status_callback_id, 1); + + clear_temp_packet(c, crypt_connection_id); + conn->status = CRYPTO_CONN_ESTABLISHED; + } + + return 0; +} + /* Handle a packet that was recieved for the connection. * * return -1 on failure. @@ -598,24 +846,7 @@ static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, uint case NET_PACKET_CRYPTO_DATA: { if (conn->status == CRYPTO_CONN_NOT_CONFIRMED || conn->status == CRYPTO_CONN_ESTABLISHED) { - uint8_t data[MAX_DATA_DATA_PACKET_SIZE]; - int len = handle_data_packet(c, crypt_connection_id, data, packet, length); - - if (len == -1) - return -1; - - if (conn->status == CRYPTO_CONN_NOT_CONFIRMED) { - if (conn->connection_status_callback) - conn->connection_status_callback(conn->connection_status_callback_object, conn->connection_status_callback_id, 1); - - clear_temp_packet(c, crypt_connection_id); - conn->status = CRYPTO_CONN_ESTABLISHED; - } - - if (conn->connection_data_callback) - conn->connection_data_callback(conn->connection_data_callback_object, conn->connection_data_callback_id, data, len); - - //TODO add buffers and packet requesting. + return handle_data_packet_helper(c, crypt_connection_id, packet, length); } else { return -1; } @@ -1053,8 +1284,8 @@ static void send_crypto_packets(Net_Crypto *c) if (conn->status >= CRYPTO_CONN_NOT_CONFIRMED && (500ULL + conn->last_data_packet_sent) < temp_time) {//TODO remove this. - uint8_t data[4] = {}; - send_data_packet(c, i, data, 4); + uint8_t data[4] = {5, 2}; + send_lossless_packet(c, i, data, 4); } } } @@ -1065,20 +1296,38 @@ static void send_crypto_packets(Net_Crypto *c) */ uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id) { + Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); + + if (conn == 0) + return 0; + //TODO - return 0; + return CRYPTO_PACKET_BUFFER_SIZE - num_packets_array(&conn->send_array); } -/* return 0 if data could not be put in packet queue. - * return 1 if data was put into the queue. - */ -int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length) -{ - //TODO - if (send_data_packet(c, crypt_connection_id, data, length) == 0) - return 1; - return 0; + + +/* return -1 if data could not be put in packet queue. + * return positive packet number if data was put into the queue. + */ +int64_t write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length) +{ + if (length == 0) + return -1; + + if (data[0] < CRYPTO_RESERVED_PACKETS) + return -1; + + Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); + + if (conn == 0) + return -1; + + if (conn->status != CRYPTO_CONN_ESTABLISHED) + return -1; + + return send_lossless_packet(c, crypt_connection_id, data, length); } /* Kill a crypto connection. diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index 0389f283..7c090aaa 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -35,18 +35,37 @@ #define CRYPTO_CONN_ESTABLISHED 4 #define CRYPTO_CONN_TIMED_OUT 5 -#define CRYPTO_PACKET_BUFFER_SIZE 64 +#define CRYPTO_PACKET_BUFFER_SIZE 64 /* Must be a power of 2 */ #define MAX_CRYPTO_PACKET_SIZE 1400 +#define CRYPTO_DATA_PACKET_MIN_SIZE (1 + sizeof(uint16_t) + (sizeof(uint32_t) + sizeof(uint32_t)) + crypto_box_MACBYTES) + /* Max size of data in packets TODO*/ -#define MAX_CRYPTO_DATA_SIZE (MAX_CRYPTO_PACKET_SIZE - (1 + sizeof(uint16_t) + crypto_box_MACBYTES)) +#define MAX_CRYPTO_DATA_SIZE (MAX_CRYPTO_PACKET_SIZE - CRYPTO_DATA_PACKET_MIN_SIZE) /* Interval in ms between sending cookie request/handshake packets. */ #define CRYPTO_SEND_PACKET_INTERVAL 500 /* The maximum number of times we try to send the cookie request and handshake before giving up. */ -#define MAX_NUM_SENDPACKET_TRIES 10 +#define MAX_NUM_SENDPACKET_TRIES 8 + +#define PACKET_ID_PADDING 0 +#define PACKET_ID_REQUEST 1 + +#define CRYPTO_RESERVED_PACKETS 16 + +typedef struct { + uint64_t time; + uint16_t length; + uint8_t data[MAX_CRYPTO_DATA_SIZE]; +} Packet_Data; + +typedef struct { + Packet_Data *buffer[CRYPTO_PACKET_BUFFER_SIZE]; + uint32_t buffer_start; + uint32_t buffer_end; /* packet numbers in array: {buffer_start, buffer_end) */ +} Packets_Array; typedef struct { uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* The real public key of the peer. */ @@ -74,6 +93,8 @@ typedef struct { IP_Port ip_port; /* The ip and port to contact this guy directly.*/ uint64_t direct_lastrecv_time; /* The Time at which we last received a direct packet in ms. */ + Packets_Array send_array; + Packets_Array recv_array; int (*connection_status_callback)(void *object, int id, uint8_t status); void *connection_status_callback_object; @@ -99,6 +120,7 @@ typedef struct { DHT *dht; Crypto_Connection *crypto_connections; + //TCP_Client_Connection *tcp_connections; uint32_t crypto_connections_length; /* Length of connections array. */ @@ -182,10 +204,10 @@ int connection_data_handler(Net_Crypto *c, int crypt_connection_id, int (*connec */ uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id); -/* return 0 if data could not be put in packet queue. - * return 1 if data was put into the queue. +/* return -1 if data could not be put in packet queue. + * return positive packet number if data was put into the queue. */ -int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length); +int64_t write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length); /* Kill a crypto connection. From 8369ac98b09e262731a42d8beafa4b403606ee25 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sun, 4 May 2014 20:33:08 -0400 Subject: [PATCH 055/117] Updated A/V to new time function. --- toxav/event.c | 7 ++++--- toxav/rtp.c | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/toxav/event.c b/toxav/event.c index ffda35ec..35af98bb 100644 --- a/toxav/event.c +++ b/toxav/event.c @@ -27,6 +27,7 @@ #endif /* HAVE_CONFIG_H */ #include +#include "../toxcore/network.h" /* current_time_monotonic() */ #include "event.h" #define _GNU_SOURCE @@ -199,7 +200,7 @@ void *event_poll( void *arg ) if ( _event_handler->timed_events ) { - uint32_t _time = ((uint32_t)(current_time() / 1000)); + uint32_t _time = ((uint32_t)current_time_monotonic()); if ( _event_handler->timed_events[0].timeout < _time ) { @@ -249,7 +250,7 @@ int throw_timer_event ( void * (func)(void *), void *arg, unsigned timeout) size_t _counter = event_handler.timed_events_count; - event_handler.timed_events[_counter - 1].timeout = timeout + ((uint32_t)(current_time() / 1000)); + event_handler.timed_events[_counter - 1].timeout = timeout + ((uint32_t)current_time_monotonic()); event_handler.timed_events[_counter - 1].id = _unique_id; ++_unique_id; @@ -330,7 +331,7 @@ int reset_timer_event ( int id, uint32_t timeout ) /* Find it and change */ for ( ; _i; _i-- ) { if ( _it->id == id ) { - _it->timeout = timeout + ((uint32_t)(current_time() / 1000)); + _it->timeout = timeout + ((uint32_t)current_time_monotonic()); break; } diff --git a/toxav/rtp.c b/toxav/rtp.c index 7307a168..9462a467 100755 --- a/toxav/rtp.c +++ b/toxav/rtp.c @@ -410,7 +410,7 @@ RTPHeader *build_header ( RTPSession *session ) ADD_SETTING_PAYLOAD ( _retu, session->payload_type ); _retu->sequnum = session->sequnum; - _retu->timestamp = ((uint32_t)(current_time() / 1000)); /* micro to milli */ + _retu->timestamp = current_time_monotonic(); /* milliseconds */ _retu->ssrc = session->ssrc; int i; From 32c8d5114c6879842e0d9143b849c0b0a1a03485 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Mon, 5 May 2014 10:00:37 -0400 Subject: [PATCH 056/117] Fixed bug. --- toxcore/net_crypto.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 9f8048be..0f06de0f 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -459,6 +459,8 @@ static int64_t read_data_beg_buffer(Packets_Array *array, Packet_Data *data) memcpy(data, array->buffer[num], sizeof(Packet_Data)); uint32_t id = array->buffer_start; ++array->buffer_start; + free(array->buffer[num]); + array->buffer[num] = NULL; return id; } From 1d87660fc48f24f9a7aa874e6fd1a6beddce8a78 Mon Sep 17 00:00:00 2001 From: Zetok Zalbavar Date: Mon, 5 May 2014 17:37:41 +0100 Subject: [PATCH 057/117] Update README.md fixes #828 closes #829 --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f2745d67..853a747d 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ With the rise of governmental monitoring programs, Tox, a FOSS initiative, aims ## The Complex Stuff: ### UDP vs. TCP Tox must use UDP simply because [hole punching](http://en.wikipedia.org/wiki/UDP_hole_punching) with TCP is not as reliable. +However, Tox does use [TCP relays](https://github.com/irungentoo/ProjectTox-Core/blob/master/docs/TCP_Network.txt) as a fallback if it encounters a firewall that prevents UDP hole punching. ### Connecting & Communicating Every peer is represented as a [byte string][String] (the public key [Tox ID] of the peer). By using torrent-style DHT, peers can find the IP of other peers by using their Tox ID. Once the IP is obtained, peers can initiate a [secure](https://github.com/irungentoo/ProjectTox-Core/wiki/Crypto) connection with each other. Once the connection is made, peers can exchange messages, send files, start video chats, etc. using encrypted communications. From 9cabfe845ec110430e42c0ec864c6d38f2af0a8c Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 6 May 2014 17:37:50 -0400 Subject: [PATCH 058/117] Removed useless code. --- toxcore/onion_client.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index ca92ee42..6ee1fe75 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c @@ -253,16 +253,9 @@ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, uint8_t *publ int index = -1; uint32_t i; - for (i = 0; i < MAX_ONION_CLIENTS; ++i) { - if (is_timeout(list_nodes[i].timestamp, ONION_NODE_TIMEOUT) - || id_closest(reference_id, list_nodes[i].client_id, public_key) == 2) { - index = i; - - if (i != 0) - break; - } else { - break; - } + if (is_timeout(list_nodes[0].timestamp, ONION_NODE_TIMEOUT) + || id_closest(reference_id, list_nodes[0].client_id, public_key) == 2) { + index = 0; } for (i = 0; i < MAX_ONION_CLIENTS; ++i) { From 9fccb80eec1398c887e2c01103770e2ffd8f27f7 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Wed, 7 May 2014 14:18:14 -0400 Subject: [PATCH 059/117] Fixed bug. memcmp is easy to confuse visually with memcpy but they do very different things. It was also comparing (copying) the senders real public key with their DHT public key. --- toxcore/onion_client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index 6ee1fe75..52fdfeaf 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c @@ -627,7 +627,7 @@ static int handle_dht_fakeid(void *object, IP_Port source, uint8_t *source_pubke if ((uint32_t)len != length - (DATA_IN_RESPONSE_MIN_SIZE + crypto_box_NONCEBYTES)) return 1; - if (memcpy(source_pubkey, packet, crypto_box_PUBLICKEYBYTES) != 0) + if (memcmp(source_pubkey, plain + 1 + sizeof(uint64_t), crypto_box_PUBLICKEYBYTES) != 0) return 1; return handle_fakeid_announce(onion_c, packet, plain, len); From 98f20c76de801d042c695b3034056b2cfbfeaab5 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 8 May 2014 18:04:46 -0400 Subject: [PATCH 060/117] Connection between toxes is lossless once again. --- toxcore/DHT.c | 2 +- toxcore/net_crypto.c | 217 ++++++++++++++++++++++++++++++++++++++++--- toxcore/net_crypto.h | 4 +- 3 files changed, 209 insertions(+), 14 deletions(-) diff --git a/toxcore/DHT.c b/toxcore/DHT.c index 4e33c02e..c23bad5d 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c @@ -1582,7 +1582,7 @@ static int friend_iplist(DHT *dht, IP_Port *ip_portlist, uint16_t friend_num) /* Send the following packet to everyone who tells us they are connected to friend_id. * * return ip for friend. - * return number of nodes the packet was sent to. (Only works if more than (MAX_FRIEND_CLIENTS / 2). + * return number of nodes the packet was sent to. (Only works if more than (MAX_FRIEND_CLIENTS / 4). */ int route_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint32_t length) { diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 0f06de0f..049e2690 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -398,12 +398,13 @@ static int add_data_to_buffer(Packets_Array *array, uint32_t number, Packet_Data return 0; } -/* Copy data with packet number to data. +/* Get pointer of data with packet number. * * return -1 on failure. - * return 0 on success. + * return 0 if data at number is empty. + * return 1 if data pointer was put in data. */ -static int copy_data_number(Packets_Array *array, Packet_Data *data, uint32_t number) +static int get_data_pointer(Packets_Array *array, Packet_Data **data, uint32_t number) { uint32_t num_spots = array->buffer_end - array->buffer_start; @@ -413,10 +414,10 @@ static int copy_data_number(Packets_Array *array, Packet_Data *data, uint32_t nu uint32_t num = number % CRYPTO_PACKET_BUFFER_SIZE; if (!array->buffer[num]) - return -1; + return 0; - memcpy(data, array->buffer[num], sizeof(Packet_Data)); - return 0; + *data = array->buffer[num]; + return 1; } /* Add data to end of array. @@ -490,10 +491,126 @@ static int clear_buffer_until(Packets_Array *array, uint32_t number) array->buffer_start = i; return 0; } + +/* Create a packet request packet from recv_array and send_buffer_end into + * data of length. + * + * return -1 on failure. + * return length of packet on success. + */ +static int generate_request_packet(uint8_t *data, uint16_t length, Packets_Array *recv_array, uint32_t send_buffer_end) +{ + if (length <= (sizeof(uint32_t) * 2)) + return -1; + + uint32_t recv_buffer_start = htonl(recv_array->buffer_start); + send_buffer_end = htonl(send_buffer_end); + memcpy(data, &recv_buffer_start, sizeof(uint32_t)); + memcpy(data + sizeof(uint32_t), &send_buffer_end, sizeof(uint32_t)); + data[sizeof(uint32_t) * 2] = PACKET_ID_REQUEST; + + uint16_t cur_len = sizeof(uint32_t) * 2 + 1; + + if (recv_array->buffer_start == recv_array->buffer_end) + return cur_len; + + if (length <= cur_len) + return cur_len; + + uint32_t i, n = 1; + + for (i = recv_array->buffer_start; i != recv_array->buffer_end; ++i) { + uint32_t num = i % CRYPTO_PACKET_BUFFER_SIZE; + + if (!recv_array->buffer[num]) { + data[cur_len] = n; + n = 0; + ++cur_len; + + if (length <= cur_len) + return cur_len; + + } else if (n == 255) { + data[cur_len] = 0; + n = 0; + ++cur_len; + + if (length <= cur_len) + return cur_len; + } + + ++n; + } + + return cur_len; +} + +/* Handle a request data packet. + * Remove all the packets the other recieved from the array. + * + * return -1 on failure. + * return 0 on success. + */ +static int handle_request_packet(Packets_Array *send_array, uint8_t *data, uint16_t length) +{ + if (length < 1) + return -1; + + if (data[0] != PACKET_ID_REQUEST) + return -1; + + if (length == 1) + return 0; + + ++data; + --length; + + uint32_t i, n = 1; + + for (i = send_array->buffer_start; i != send_array->buffer_end; ++i) { + if (length == 0) + break; + + uint32_t num = i % CRYPTO_PACKET_BUFFER_SIZE; + + if (n == data[0]) { + if (send_array->buffer[num]) { + send_array->buffer[num]->time = 0; + } + + ++data; + --length; + n = 0; + } else { + free(send_array->buffer[num]); + send_array->buffer[num] = NULL; + } + + if (n == 255) { + n = 1; + + if (data[0] != 0) + return -1; + + ++data; + --length; + } else { + ++n; + } + } + + return 0; +} + /** END: Array Related functions **/ #define MAX_DATA_DATA_PACKET_SIZE (MAX_CRYPTO_PACKET_SIZE - (1 + sizeof(uint16_t) + crypto_box_MACBYTES)) +/* Creates and sends a data packet to the peer using the fastest route. + * + * return -1 on failure. + * return 0 on success. + */ static int send_data_packet(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint16_t length) { if (length == 0 || length + (1 + sizeof(uint16_t) + crypto_box_MACBYTES) > MAX_CRYPTO_PACKET_SIZE) @@ -517,6 +634,11 @@ static int send_data_packet(Net_Crypto *c, int crypt_connection_id, uint8_t *dat return send_packet_to(c, crypt_connection_id, packet, sizeof(packet)); } +/* Creates and sends a data packet with buffer_start and num to the peer using the fastest route. + * + * return -1 on failure. + * return 0 on success. + */ static int send_data_packet_helper(Net_Crypto *c, int crypt_connection_id, uint32_t buffer_start, uint32_t num, uint8_t *data, uint32_t length) { @@ -608,6 +730,64 @@ static int handle_data_packet(Net_Crypto *c, int crypt_connection_id, uint8_t *d return len; } +/* Send a request packet. + * + * return -1 on failure. + * return 0 on success. + */ +static int send_request_packet(Net_Crypto *c, int crypt_connection_id) +{ + Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); + + if (conn == 0) + return -1; + + uint8_t packet[MAX_DATA_DATA_PACKET_SIZE]; + int len = generate_request_packet(packet, sizeof(packet), &conn->recv_array, conn->send_array.buffer_end); + + if (len == -1) + return -1; + + return send_data_packet(c, crypt_connection_id, packet, len); +} + +/* Send up to max num previously requested data packets. + * + * return -1 on failure. + * return 0 on success. + */ +static int send_requested_packets(Net_Crypto *c, int crypt_connection_id, uint16_t max_num) +{ + Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); + + if (conn == 0) + return -1; + + uint32_t i; + + for (i = 0; i < max_num; ++i) { + Packet_Data *dt; + uint32_t packet_num = (i + conn->send_array.buffer_start); + int ret = get_data_pointer(&conn->send_array, &dt, packet_num); + + if (ret == -1) { + return -1; + } else if (ret == 0) { + continue; + } + + if (dt->time != 0) { + continue; + } + + dt->time = current_time_monotonic(); + + if (send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, packet_num, dt->data, + dt->length) != 0) + printf("send_data_packet failed\n"); + } +} + /* Add a new temp packet to send repeatedly. * @@ -754,11 +934,12 @@ static int handle_data_packet_helper(Net_Crypto *c, int crypt_connection_id, uin } if (real_data[0] == PACKET_ID_REQUEST) { - if (real_length <= 1) + if (handle_request_packet(&conn->send_array, real_data, real_length) != 0) { + printf("fail %u %u\n", real_data[0], real_length); return -1; + } - - //TODO + //TODO: use num. } else { Packet_Data dt; dt.time = current_time_monotonic(); @@ -773,6 +954,16 @@ static int handle_data_packet_helper(Net_Crypto *c, int crypt_connection_id, uin conn->connection_data_callback(conn->connection_data_callback_object, conn->connection_data_callback_id, dt.data, dt.length); } + + //send a data request packet for every x number of data packets recieved. + ++conn->packet_counter; + + if (conn->packet_counter > (CRYPTO_PACKET_BUFFER_SIZE / 4)) { + if (send_request_packet(c, crypt_connection_id) != 0) + return -1; + + conn->packet_counter = 0; + } } if (conn->status == CRYPTO_CONN_NOT_CONFIRMED) { @@ -1285,10 +1476,12 @@ static void send_crypto_packets(Net_Crypto *c) } if (conn->status >= CRYPTO_CONN_NOT_CONFIRMED - && (500ULL + conn->last_data_packet_sent) < temp_time) {//TODO remove this. - uint8_t data[4] = {5, 2}; - send_lossless_packet(c, i, data, 4); + && (CRYPTO_SEND_PACKET_INTERVAL + conn->last_data_packet_sent) < temp_time) { + send_request_packet(c, i); } + + //TODO + send_requested_packets(c, i, ~0); } } diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index 7c090aaa..b3964064 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -35,7 +35,7 @@ #define CRYPTO_CONN_ESTABLISHED 4 #define CRYPTO_CONN_TIMED_OUT 5 -#define CRYPTO_PACKET_BUFFER_SIZE 64 /* Must be a power of 2 */ +#define CRYPTO_PACKET_BUFFER_SIZE 128 /* Must be a power of 2 */ #define MAX_CRYPTO_PACKET_SIZE 1400 @@ -105,6 +105,8 @@ typedef struct { int connection_data_callback_id; uint64_t last_data_packet_sent; + + uint32_t packet_counter; } Crypto_Connection; typedef struct { From 89022326d3742defd9c7b1111ddcda53688d85be Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 8 May 2014 18:07:51 -0400 Subject: [PATCH 061/117] Fixed major denial of service issue. --- toxcore/network.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/toxcore/network.c b/toxcore/network.c index 7813ab03..329bcf9a 100644 --- a/toxcore/network.c +++ b/toxcore/network.c @@ -297,7 +297,6 @@ int sendpacket(Networking_Core *net, IP_Port ip_port, uint8_t *data, uint32_t le * ip and port of sender is put into ip_port. * Packet data is put into data. * Packet length is put into length. - * Dump all empty packets. */ static int receivepacket(sock_t sock, IP_Port *ip_port, uint8_t *data, uint32_t *length) { @@ -311,7 +310,7 @@ static int receivepacket(sock_t sock, IP_Port *ip_port, uint8_t *data, uint32_t *length = 0; int fail_or_len = recvfrom(sock, (char *) data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrlen); - if (fail_or_len <= 0) { + if (fail_or_len < 0) { #ifdef LOGGING if ((fail_or_len < 0) && (errno != EWOULDBLOCK)) { @@ -320,7 +319,7 @@ static int receivepacket(sock_t sock, IP_Port *ip_port, uint8_t *data, uint32_t } #endif - return -1; /* Nothing received or empty packet. */ + return -1; /* Nothing received. */ } *length = (uint32_t)fail_or_len; From b0731f54cd6c891283565e0082ad06481c274415 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 9 May 2014 21:46:37 -0400 Subject: [PATCH 062/117] Fixed small issues. Added set_buffer_end(). File transfer test now checks if pieces arrive correctly. --- auto_tests/tox_test.c | 15 ++++++++++---- toxcore/Messenger.c | 2 ++ toxcore/net_crypto.c | 47 +++++++++++++++++++++++++++++++++---------- toxcore/net_crypto.h | 4 +--- 4 files changed, 50 insertions(+), 18 deletions(-) diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c index 13c4fc7b..5723d1c3 100644 --- a/auto_tests/tox_test.c +++ b/auto_tests/tox_test.c @@ -96,16 +96,21 @@ void file_print_control(Tox *m, int friendnumber, uint8_t send_recieve, uint8_t } uint64_t size_recv; +uint8_t num; void write_file(Tox *m, int friendnumber, uint8_t filenumber, uint8_t *data, uint16_t length, void *userdata) { if (*((uint32_t *)userdata) != 974536) return; uint8_t *f_data = malloc(length); - memset(f_data, 6, length); + memset(f_data, num, length); + ++num; - if (memcmp(f_data, data, length) == 0) + if (memcmp(f_data, data, length) == 0) { size_recv += length; + } else { + printf("FILE_CORRUPTED\n"); + } } START_TEST(test_few_clients) @@ -228,8 +233,8 @@ START_TEST(test_few_clients) ck_assert_msg(fnum != -1, "tox_new_file_sender fail"); int fpiece_size = tox_file_data_size(tox2, 0); uint8_t *f_data = malloc(fpiece_size); - memset(f_data, 6, fpiece_size); - + uint8_t num = 0; + memset(f_data, num, fpiece_size); while (1) { file_sent = 0; tox_do(tox1); @@ -242,6 +247,8 @@ START_TEST(test_few_clients) sendf_ok = 0; tox_file_send_control(tox2, 0, 0, fnum, TOX_FILECONTROL_FINISHED, NULL, 0); } + ++num; + memset(f_data, num, fpiece_size); totalf_size -= fpiece_size; } diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index fc8bd9bb..c877d565 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -1835,10 +1835,12 @@ void kill_messenger(Messenger *m) kill_net_crypto(m->net_crypto); kill_DHT(m->dht); kill_networking(m->net); + for (i = 0; i < m->numfriends; ++i) { if (m->friendlist[i].statusmessage) free(m->friendlist[i].statusmessage); } + free(m->friendlist); free(m); } diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 049e2690..b95791f1 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -492,6 +492,23 @@ static int clear_buffer_until(Packets_Array *array, uint32_t number) return 0; } +/* Set array buffer end to number. + * + * return -1 on failure. + * return 0 on success. + */ +static int set_buffer_end(Packets_Array *array, uint32_t number) +{ + if ((number - array->buffer_start) > CRYPTO_PACKET_BUFFER_SIZE) + return -1; + + if ((number - array->buffer_end) > CRYPTO_PACKET_BUFFER_SIZE) + return -1; + + array->buffer_end = number; + return 0; +} + /* Create a packet request packet from recv_array and send_buffer_end into * data of length. * @@ -549,7 +566,7 @@ static int generate_request_packet(uint8_t *data, uint16_t length, Packets_Array * Remove all the packets the other recieved from the array. * * return -1 on failure. - * return 0 on success. + * return number of requested packets on success. */ static int handle_request_packet(Packets_Array *send_array, uint8_t *data, uint16_t length) { @@ -566,6 +583,7 @@ static int handle_request_packet(Packets_Array *send_array, uint8_t *data, uint1 --length; uint32_t i, n = 1; + uint32_t requested = 0; for (i = send_array->buffer_start; i != send_array->buffer_end; ++i) { if (length == 0) @@ -581,6 +599,7 @@ static int handle_request_packet(Packets_Array *send_array, uint8_t *data, uint1 ++data; --length; n = 0; + ++requested; } else { free(send_array->buffer[num]); send_array->buffer[num] = NULL; @@ -599,7 +618,7 @@ static int handle_request_packet(Packets_Array *send_array, uint8_t *data, uint1 } } - return 0; + return requested; } /** END: Array Related functions **/ @@ -630,7 +649,6 @@ static int send_data_packet(Net_Crypto *c, int crypt_connection_id, uint8_t *dat return -1; increment_nonce(conn->sent_nonce); - conn->last_data_packet_sent = current_time_monotonic(); //TODO remove this. return send_packet_to(c, crypt_connection_id, packet, sizeof(packet)); } @@ -754,7 +772,7 @@ static int send_request_packet(Net_Crypto *c, int crypt_connection_id) /* Send up to max num previously requested data packets. * * return -1 on failure. - * return 0 on success. + * return number of packets sent on success. */ static int send_requested_packets(Net_Crypto *c, int crypt_connection_id, uint16_t max_num) { @@ -763,7 +781,7 @@ static int send_requested_packets(Net_Crypto *c, int crypt_connection_id, uint16 if (conn == 0) return -1; - uint32_t i; + uint32_t i, num_sent = 0; for (i = 0; i < max_num; ++i) { Packet_Data *dt; @@ -783,9 +801,11 @@ static int send_requested_packets(Net_Crypto *c, int crypt_connection_id, uint16 dt->time = current_time_monotonic(); if (send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, packet_num, dt->data, - dt->length) != 0) - printf("send_data_packet failed\n"); + dt->length) == 0) + ++num_sent; } + + return num_sent; } @@ -934,12 +954,14 @@ static int handle_data_packet_helper(Net_Crypto *c, int crypt_connection_id, uin } if (real_data[0] == PACKET_ID_REQUEST) { - if (handle_request_packet(&conn->send_array, real_data, real_length) != 0) { + int requested = handle_request_packet(&conn->send_array, real_data, real_length); + + if (requested == -1) { printf("fail %u %u\n", real_data[0], real_length); return -1; } - //TODO: use num. + set_buffer_end(&conn->recv_array, num); } else { Packet_Data dt; dt.time = current_time_monotonic(); @@ -1476,8 +1498,11 @@ static void send_crypto_packets(Net_Crypto *c) } if (conn->status >= CRYPTO_CONN_NOT_CONFIRMED - && (CRYPTO_SEND_PACKET_INTERVAL + conn->last_data_packet_sent) < temp_time) { - send_request_packet(c, i); + && (CRYPTO_SEND_PACKET_INTERVAL + conn->last_request_packet_sent) < temp_time) { + if (send_request_packet(c, i) == 0) { + conn->last_request_packet_sent = temp_time; + } + } //TODO diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index b3964064..b06fcb10 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -26,8 +26,6 @@ #include "DHT.h" -#define CRYPTO_HANDSHAKE_TIMEOUT (CONNECTION_TIMEOUT * 2) - #define CRYPTO_CONN_NO_CONNECTION 0 #define CRYPTO_CONN_COOKIE_REQUESTING 1 //send cookie request packets #define CRYPTO_CONN_HANDSHAKE_SENT 2 //send handshake packets @@ -104,7 +102,7 @@ typedef struct { void *connection_data_callback_object; int connection_data_callback_id; - uint64_t last_data_packet_sent; + uint64_t last_request_packet_sent; uint32_t packet_counter; } Crypto_Connection; From 1e485b2c2f210f173dbae0a480e43daadd32a71a Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 10 May 2014 13:42:59 -0400 Subject: [PATCH 063/117] Added basic congestion control to net_crypto. --- toxcore/net_crypto.c | 103 ++++++++++++++++++++++++++++++++++++------- toxcore/net_crypto.h | 16 ++++++- 2 files changed, 101 insertions(+), 18 deletions(-) diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index b95791f1..9d0b6cca 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -693,7 +693,7 @@ static int64_t send_lossless_packet(Net_Crypto *c, int crypt_connection_id, uint return -1; if (send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, packet_num, data, length) != 0) - printf("send_data_packet failed\n"); + fprintf(stderr, "send_data_packet failed\n"); return packet_num; } @@ -776,14 +776,17 @@ static int send_request_packet(Net_Crypto *c, int crypt_connection_id) */ static int send_requested_packets(Net_Crypto *c, int crypt_connection_id, uint16_t max_num) { + if (max_num == 0) + return -1; + Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); if (conn == 0) return -1; - uint32_t i, num_sent = 0; + uint32_t i, num_sent = 0, array_size = num_packets_array(&conn->send_array); - for (i = 0; i < max_num; ++i) { + for (i = 0; i < array_size; ++i) { Packet_Data *dt; uint32_t packet_num = (i + conn->send_array.buffer_start); int ret = get_data_pointer(&conn->send_array, &dt, packet_num); @@ -803,6 +806,9 @@ static int send_requested_packets(Net_Crypto *c, int crypt_connection_id, uint16 if (send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, packet_num, dt->data, dt->length) == 0) ++num_sent; + + if (num_sent >= max_num) + break; } return num_sent; @@ -957,8 +963,9 @@ static int handle_data_packet_helper(Net_Crypto *c, int crypt_connection_id, uin int requested = handle_request_packet(&conn->send_array, real_data, real_length); if (requested == -1) { - printf("fail %u %u\n", real_data[0], real_length); return -1; + } else { + //TODO? } set_buffer_end(&conn->recv_array, num); @@ -977,15 +984,8 @@ static int handle_data_packet_helper(Net_Crypto *c, int crypt_connection_id, uin dt.length); } - //send a data request packet for every x number of data packets recieved. + /* Packet counter. */ ++conn->packet_counter; - - if (conn->packet_counter > (CRYPTO_PACKET_BUFFER_SIZE / 4)) { - if (send_request_packet(c, crypt_connection_id) != 0) - return -1; - - conn->packet_counter = 0; - } } if (conn->status == CRYPTO_CONN_NOT_CONFIRMED) { @@ -1291,6 +1291,7 @@ int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c) send_temp_packet(c, crypt_connection_id); conn->status = CRYPTO_CONN_NOT_CONFIRMED; + conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE; crypto_connection_add_source(c, crypt_connection_id, n_c->source); return crypt_connection_id; } @@ -1322,6 +1323,7 @@ int new_crypto_connection(Net_Crypto *c, uint8_t *real_public_key) random_nonce(conn->sent_nonce); crypto_box_keypair(conn->sessionpublic_key, conn->sessionsecret_key); conn->status = CRYPTO_CONN_COOKIE_REQUESTING; + conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE; return crypt_connection_id; } @@ -1482,6 +1484,14 @@ static int udp_handle_packet(void *object, IP_Port source, uint8_t *packet, uint return 0; } +/* The dT for the average packet recieving rate calculations. + Also used as the */ +#define PACKET_COUNTER_AVERAGE_INTERVAL 200 + +/* Ratio of recv queue size / recv packet rate (in seconds) times + * the number of ms between request packets to send at that ratio + */ +#define REQUEST_PACKETS_COMPARE_CONSTANT (0.5 * 100.0) static void send_crypto_packets(Net_Crypto *c) { uint32_t i; @@ -1505,8 +1515,58 @@ static void send_crypto_packets(Net_Crypto *c) } - //TODO - send_requested_packets(c, i, ~0); + if (conn->status == CRYPTO_CONN_ESTABLISHED) { + if (((double)num_packets_array(&conn->recv_array) / (conn->packet_recv_rate + 1.0)) * (double)( + temp_time - conn->last_request_packet_sent) > REQUEST_PACKETS_COMPARE_CONSTANT) { + if (send_request_packet(c, i) == 0) { + conn->last_request_packet_sent = temp_time; + } + } + + if ((PACKET_COUNTER_AVERAGE_INTERVAL + conn->packet_counter_set) < temp_time) { + conn->packet_recv_rate = (double)conn->packet_counter / ((double)(temp_time - conn->packet_counter_set) / 1000.0); + conn->packet_counter = 0; + conn->packet_counter_set = temp_time; + + if ((double)num_packets_array(&conn->send_array) < 0.3 * (conn->packet_send_rate)) { + conn->packet_send_rate *= 1.2; + } else if ((double)num_packets_array(&conn->send_array) > 0.5 * (conn->packet_send_rate)) { + conn->packet_send_rate *= 0.8; + } + + if (conn->packet_send_rate < CRYPTO_PACKET_MIN_RATE || !conn->sending) + conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE; + + if (conn->packet_send_rate > CRYPTO_PACKET_BUFFER_SIZE * 8) + conn->packet_send_rate = CRYPTO_PACKET_BUFFER_SIZE * 8; + + } + + if (conn->last_packets_left_set == 0) { + conn->last_packets_left_set = temp_time; + conn->packets_left = conn->packet_send_rate; + } else if (((1000.0 / conn->packet_send_rate) + conn->last_packets_left_set) < temp_time) { + uint32_t num_packets = conn->packet_send_rate * ((double)(temp_time - conn->last_packets_left_set) / 1000.0); + + if (conn->packets_left > num_packets * 2 + CRYPTO_MIN_QUEUE_LENGTH) { + conn->packets_left = num_packets * 2 + CRYPTO_MIN_QUEUE_LENGTH; + } else { + conn->packets_left += num_packets; + } + + conn->last_packets_left_set = temp_time; + } + + int ret = send_requested_packets(c, i, conn->packets_left); + + if (ret != -1) { + conn->packets_left -= ret; + } + + if (conn->sending != 0 && num_packets_array(&conn->send_array) < CRYPTO_MIN_QUEUE_LENGTH) { + --conn->sending; + } + } } } @@ -1521,8 +1581,7 @@ uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id) if (conn == 0) return 0; - //TODO - return CRYPTO_PACKET_BUFFER_SIZE - num_packets_array(&conn->send_array); + return conn->packets_left; } @@ -1547,7 +1606,17 @@ int64_t write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, if (conn->status != CRYPTO_CONN_ESTABLISHED) return -1; - return send_lossless_packet(c, crypt_connection_id, data, length); + if (conn->packets_left == 0) + return -1; + + int64_t ret = send_lossless_packet(c, crypt_connection_id, data, length); + + if (ret == -1) + return -1; + + --conn->packets_left; + conn->sending = CRYPTO_MIN_QUEUE_LENGTH; + return ret; } /* Kill a crypto connection. diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index b06fcb10..ba5ed924 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -33,7 +33,13 @@ #define CRYPTO_CONN_ESTABLISHED 4 #define CRYPTO_CONN_TIMED_OUT 5 -#define CRYPTO_PACKET_BUFFER_SIZE 128 /* Must be a power of 2 */ +#define CRYPTO_PACKET_BUFFER_SIZE 16384 /* Must be a power of 2 */ + +/* Minimum packet rate per second. */ +#define CRYPTO_PACKET_MIN_RATE 40.0 + +/* Minimum packet queue max length. */ +#define CRYPTO_MIN_QUEUE_LENGTH 8 #define MAX_CRYPTO_PACKET_SIZE 1400 @@ -105,6 +111,14 @@ typedef struct { uint64_t last_request_packet_sent; uint32_t packet_counter; + double packet_recv_rate; + uint64_t packet_counter_set; + + double packet_send_rate; + uint32_t packets_left; + uint64_t last_packets_left_set; + + uint8_t sending; /* indicates if data is being sent or not. */ } Crypto_Connection; typedef struct { From ff4368add70d4e36dd553fdc32efe38bdef677b9 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 10 May 2014 16:09:44 -0400 Subject: [PATCH 064/117] Fixed build by adding librt to build system. --- configure.ac | 11 +++++++++++ toxcore/Makefile.inc | 1 + 2 files changed, 12 insertions(+) diff --git a/configure.ac b/configure.ac index 34038517..7756e6b9 100644 --- a/configure.ac +++ b/configure.ac @@ -388,6 +388,17 @@ AC_C_BIGENDIAN # Checks for library functions. AC_FUNC_FORK AC_CHECK_FUNCS([gettimeofday memset socket strchr malloc]) +if test "x$WIN32" != "xyes"; then + AC_CHECK_LIB(rt, clock_gettime, + [ + RT_LIBS="-lrt" + AC_SUBST(RT_LIBS) + ], + [ + AC_MSG_ERROR([required library rt was not found on your system]) + ] + ) +fi if test "x$BUILD_AV" = "xyes"; then AX_PTHREAD( diff --git a/toxcore/Makefile.inc b/toxcore/Makefile.inc index 926b4e3f..4c959789 100644 --- a/toxcore/Makefile.inc +++ b/toxcore/Makefile.inc @@ -50,6 +50,7 @@ libtoxcore_la_LDFLAGS = $(TOXCORE_LT_LDFLAGS) \ $(EXTRA_LT_LDFLAGS) \ $(LIBSODIUM_LDFLAGS) \ $(NACL_LDFLAGS) \ + $(RT_LIBS) \ $(WINSOCK2_LIBS) libtoxcore_la_LIBADD = $(LIBSODIUM_LIBS) \ From 1580a5c696478aec1b17946e323a4091430106c5 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sun, 11 May 2014 18:27:23 -0400 Subject: [PATCH 065/117] Added kill packets. There should be no more delay between a peer closing their client and their friend being notified of them going offline. (unless the kill packet is lost) --- docs/Tox_middle_level_network_protocol.txt | 1 + toxcore/net_crypto.c | 26 ++++++++++++++++++++++ toxcore/net_crypto.h | 3 +++ 3 files changed, 30 insertions(+) diff --git a/docs/Tox_middle_level_network_protocol.txt b/docs/Tox_middle_level_network_protocol.txt index f9b03196..29ea131a 100644 --- a/docs/Tox_middle_level_network_protocol.txt +++ b/docs/Tox_middle_level_network_protocol.txt @@ -100,6 +100,7 @@ lossy][data] data ids: 0: padding (skipped until we hit a non zero (data id) byte) 1: packet request packet (lossy packet) +2: connection kill packet (lossy packet) (tells the other that the connection is over) ... 16+: reserved for Messenger usage (lossless packets). diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 9d0b6cca..5770121e 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -918,6 +918,23 @@ static int create_send_handshake(Net_Crypto *c, int crypt_connection_id, uint8_t return 0; } +/* Send a kill packet. + * + * return -1 on failure. + * return 0 on success. + */ +static int send_kill_packet(Net_Crypto *c, int crypt_connection_id) +{ + Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); + + if (conn == 0) + return -1; + + uint8_t kill_packet = PACKET_ID_KILL; + return send_data_packet_helper(c, crypt_connection_id, conn->recv_array.buffer_start, conn->send_array.buffer_end, + &kill_packet, sizeof(kill_packet)); +} + /* Handle a recieved data packet. * * return -1 on failure. @@ -969,6 +986,9 @@ static int handle_data_packet_helper(Net_Crypto *c, int crypt_connection_id, uin } set_buffer_end(&conn->recv_array, num); + } else if (real_data[0] == PACKET_ID_KILL) { + conn->killed = 1; + return 0; } else { Packet_Data dt; dt.time = current_time_monotonic(); @@ -1627,6 +1647,7 @@ int64_t write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, int crypto_kill(Net_Crypto *c, int crypt_connection_id) { //TODO + send_kill_packet(c, crypt_connection_id); return wipe_crypto_connection(c, crypt_connection_id); } @@ -1713,6 +1734,11 @@ static void kill_timedout(Net_Crypto *c) if (conn->temp_packet_num_sent < MAX_NUM_SENDPACKET_TRIES) continue; + conn->killed = 1; + + } + + if (conn->killed) { if (conn->connection_status_callback) { conn->connection_status_callback(conn->connection_status_callback_object, conn->connection_status_callback_id, 0); crypto_kill(c, i); diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index ba5ed924..7d616be6 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -56,6 +56,7 @@ #define PACKET_ID_PADDING 0 #define PACKET_ID_REQUEST 1 +#define PACKET_ID_KILL 2 #define CRYPTO_RESERVED_PACKETS 16 @@ -119,6 +120,8 @@ typedef struct { uint64_t last_packets_left_set; uint8_t sending; /* indicates if data is being sent or not. */ + + uint8_t killed; /* set to 1 to kill the connection. */ } Crypto_Connection; typedef struct { From 87cec792062a755675e53b5603049cdb067aa70f Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sun, 11 May 2014 19:35:23 -0400 Subject: [PATCH 066/117] Fixed issue where callbacks were not set for accepted connection. --- toxcore/Messenger.c | 9 ++++++++- toxcore/net_crypto.c | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index c877d565..ced1e845 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -1738,6 +1738,9 @@ static void LANdiscovery(Messenger *m) } } +static int handle_status(void *object, int i, uint8_t status); +static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len); + static int handle_new_connections(void *object, New_Connection *n_c) { Messenger *m = object; @@ -1747,8 +1750,12 @@ static int handle_new_connections(void *object, New_Connection *n_c) if (m->friendlist[friend_id].crypt_connection_id != -1) return -1; - m->friendlist[friend_id].crypt_connection_id = accept_crypto_connection(m->net_crypto, n_c); + int id = accept_crypto_connection(m->net_crypto, n_c); + connection_status_handler(m->net_crypto, id, &handle_status, m, friend_id); + connection_data_handler(m->net_crypto, id, &handle_packet, m, friend_id); + m->friendlist[friend_id].crypt_connection_id = id; set_friend_status(m, friend_id, FRIEND_CONFIRMED); + return 0; } return -1; diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 5770121e..a5149a7c 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -1527,7 +1527,7 @@ static void send_crypto_packets(Net_Crypto *c) send_temp_packet(c, i); } - if (conn->status >= CRYPTO_CONN_NOT_CONFIRMED + if ((conn->status == CRYPTO_CONN_NOT_CONFIRMED || conn->status == CRYPTO_CONN_ESTABLISHED) && (CRYPTO_SEND_PACKET_INTERVAL + conn->last_request_packet_sent) < temp_time) { if (send_request_packet(c, i) == 0) { conn->last_request_packet_sent = temp_time; From 10da970e0dfcb21fda4da96635b690065375daff Mon Sep 17 00:00:00 2001 From: irungentoo Date: Mon, 12 May 2014 14:07:03 -0400 Subject: [PATCH 067/117] Added ping_array, a special efficient array for use in operations that require sending ping type packets. Made ping packets use it. --- toxcore/Makefile.inc | 2 + toxcore/ping.c | 135 +++++++++--------------------------- toxcore/ping_array.c | 162 +++++++++++++++++++++++++++++++++++++++++++ toxcore/ping_array.h | 75 ++++++++++++++++++++ 4 files changed, 272 insertions(+), 102 deletions(-) create mode 100644 toxcore/ping_array.c create mode 100644 toxcore/ping_array.h diff --git a/toxcore/Makefile.inc b/toxcore/Makefile.inc index 4c959789..7c1cf66e 100644 --- a/toxcore/Makefile.inc +++ b/toxcore/Makefile.inc @@ -11,6 +11,8 @@ libtoxcore_la_SOURCES = ../toxcore/DHT.h \ ../toxcore/network.c \ ../toxcore/crypto_core.h \ ../toxcore/crypto_core.c \ + ../toxcore/ping_array.h \ + ../toxcore/ping_array.c \ ../toxcore/net_crypto.h \ ../toxcore/net_crypto.c \ ../toxcore/friend_requests.h \ diff --git a/toxcore/ping.c b/toxcore/ping.c index 35aab86f..52817cd6 100644 --- a/toxcore/ping.c +++ b/toxcore/ping.c @@ -34,6 +34,7 @@ #include "network.h" #include "util.h" +#include "ping_array.h" #define PING_NUM_MAX 512 @@ -43,109 +44,18 @@ /* Ping newly announced nodes to ping per TIME_TO_PING seconds*/ #define TIME_TO_PING 3 -typedef struct { - IP_Port ip_port; - uint64_t id; - uint64_t timestamp; - uint8_t shared_key[crypto_box_BEFORENMBYTES]; -} pinged_t; struct PING { DHT *dht; - pinged_t pings[PING_NUM_MAX]; - size_t num_pings; - size_t pos_pings; - + Ping_Array ping_array; Node_format to_ping[MAX_TO_PING]; uint64_t last_to_ping; }; -static int is_ping_timeout(uint64_t time) -{ - return is_timeout(time, PING_TIMEOUT); -} - -static void remove_timeouts(PING *ping) // O(n) -{ - size_t i, id; - size_t new_pos = ping->pos_pings; - size_t new_num = ping->num_pings; - - // Loop through buffer, oldest first. - for (i = 0; i < ping->num_pings; i++) { - id = (ping->pos_pings + i) % PING_NUM_MAX; - - if (is_ping_timeout(ping->pings[id].timestamp)) { - new_pos++; - new_num--; - } - // Break here because list is sorted. - else { - break; - } - } - - ping->num_pings = new_num; - ping->pos_pings = new_pos % PING_NUM_MAX; -} - -static uint64_t add_ping(PING *ping, IP_Port ipp, uint8_t *shared_encryption_key) // O(n) -{ - size_t p; - - remove_timeouts(ping); - - /* Remove oldest ping if full buffer. */ - if (ping->num_pings == PING_NUM_MAX) { - ping->num_pings--; - ping->pos_pings = (ping->pos_pings + 1) % PING_NUM_MAX; - } - - /* Insert new ping at end of list. */ - p = (ping->pos_pings + ping->num_pings) % PING_NUM_MAX; - - ping->pings[p].ip_port = ipp; - ping->pings[p].timestamp = unix_time(); - ping->pings[p].id = random_64b(); - memcpy(ping->pings[p].shared_key, shared_encryption_key, crypto_box_BEFORENMBYTES); - - ping->num_pings++; - return ping->pings[p].id; -} - -/* checks if ip/port or ping_id are already in the list to ping - * if both are set, both must match, otherwise the set must match - * - * returns 0 if neither is set or no match was found - * returns the (index + 1) of the match if one was found - */ -static int is_pinging(PING *ping, IP_Port ipp, uint64_t ping_id) -{ - // O(n) TODO: Replace this with something else. - - /* at least one MUST be set */ - uint8_t ip_valid = ip_isset(&ipp.ip); - - if (!ip_valid && !ping_id) - return 0; - - size_t i; - - remove_timeouts(ping); - - for (i = 0; i < ping->num_pings; i++) { - size_t id = (ping->pos_pings + i) % PING_NUM_MAX; - - if (!ping_id || (ping->pings[id].id == ping_id)) - if (!ip_valid || ipport_equal(&ping->pings[id].ip_port, &ipp)) - return id + 1; - } - - return 0; -} #define DHT_PING_SIZE (1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(uint64_t) + crypto_box_MACBYTES) +#define PING_DATA_SIZE (CLIENT_ID_SIZE + sizeof(IP_Port)) int send_ping_request(PING *ping, IP_Port ipp, uint8_t *client_id) { @@ -153,7 +63,7 @@ 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->dht->self_public_key)) + if (id_equal(client_id, ping->dht->self_public_key)) return 1; uint8_t shared_key[crypto_box_BEFORENMBYTES]; @@ -161,7 +71,13 @@ int send_ping_request(PING *ping, IP_Port ipp, uint8_t *client_id) // generate key to encrypt ping_id with recipient privkey DHT_get_shared_key_sent(ping->dht, shared_key, client_id); // Generate random ping_id. - ping_id = add_ping(ping, ipp, shared_key); + uint8_t data[PING_DATA_SIZE]; + id_copy(data, client_id); + memcpy(data + CLIENT_ID_SIZE, &ipp, sizeof(IP_Port)); + ping_id = ping_array_add(&ping->ping_array, data, sizeof(data)); + + if (ping_id == 0) + return 1; pk[0] = NET_PACKET_PING_REQUEST; id_copy(pk + 1, ping->dht->self_public_key); // Our pubkey @@ -252,14 +168,13 @@ static int handle_ping_response(void *_dht, IP_Port source, uint8_t *packet, uin if (id_equal(packet + 1, ping->dht->self_public_key)) return 1; - int ping_index = is_pinging(ping, source, 0); + uint8_t shared_key[crypto_box_BEFORENMBYTES]; - if (!ping_index) - return 1; + // generate key to encrypt ping_id with recipient privkey + DHT_get_shared_key_sent(ping->dht, shared_key, packet + 1); - --ping_index; // Decrypt ping_id - rc = decrypt_data_symmetric(ping->pings[ping_index].shared_key, + rc = decrypt_data_symmetric(shared_key, packet + 1 + CLIENT_ID_SIZE, packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, sizeof(ping_id) + crypto_box_MACBYTES, @@ -268,11 +183,21 @@ static int handle_ping_response(void *_dht, IP_Port source, uint8_t *packet, uin if (rc != sizeof(ping_id)) return 1; - if (ping->pings[ping_index].id != ping_id) + uint8_t data[PING_DATA_SIZE]; + + if (ping_array_check(data, sizeof(data), &ping->ping_array, ping_id) != sizeof(data)) + return 1; + + if (!id_equal(packet + 1, data)) + return 1; + + IP_Port ipp; + memcpy(&ipp, data + CLIENT_ID_SIZE, sizeof(IP_Port)); + + if (!ipport_equal(&ipp, &source)) return 1; addto_lists(dht, source, packet + 1); - return 0; } @@ -348,6 +273,11 @@ PING *new_ping(DHT *dht) if (ping == NULL) return NULL; + if (ping_array_init(&ping->ping_array, PING_NUM_MAX, PING_TIMEOUT) != 0) { + free(ping); + return NULL; + } + 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); @@ -359,6 +289,7 @@ void kill_ping(PING *ping) { networking_registerhandler(ping->dht->net, NET_PACKET_PING_REQUEST, NULL, NULL); networking_registerhandler(ping->dht->net, NET_PACKET_PING_RESPONSE, NULL, NULL); + ping_array_free_all(&ping->ping_array); free(ping); } diff --git a/toxcore/ping_array.c b/toxcore/ping_array.c new file mode 100644 index 00000000..cb18ceb3 --- /dev/null +++ b/toxcore/ping_array.c @@ -0,0 +1,162 @@ +/* ping_array.c + * + * Implementation of an efficient array to store that we pinged something. + * + * + * Copyright (C) 2014 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "ping_array.h" +#include "crypto_core.h" +#include "util.h" + +static void clear_entry(Ping_Array *array, uint32_t index) +{ + free(array->entries[index].data); + array->entries[index].data = NULL; + array->entries[index].length = + array->entries[index].time = + array->entries[index].ping_id = 0; +} + +/* Clear timed out entries. + */ +static void ping_array_clear_timedout(Ping_Array *array) +{ + while (array->last_deleted != array->last_added) { + uint32_t index = array->last_deleted % array->total_size; + + if (!is_timeout(array->entries[index].time, array->timeout)) + break; + + clear_entry(array, index); + ++array->last_deleted; + } +} + +/* Add a data with length to the Ping_Array list and return a ping_id. + * + * return ping_id on success. + * return 0 on failure. + */ +uint64_t ping_array_add(Ping_Array *array, uint8_t *data, uint32_t length) +{ + ping_array_clear_timedout(array); + uint32_t index = array->last_added % array->total_size; + + if (array->entries[index].data != NULL) { + array->last_deleted = array->last_added - array->total_size; + clear_entry(array, index); + } + + array->entries[index].data = malloc(length); + + if (array->entries[index].data == NULL) + return 0; + + memcpy(array->entries[index].data, data, length); + array->entries[index].length = length; + array->entries[index].time = unix_time(); + ++array->last_added; + uint64_t ping_id = random_64b(); + ping_id /= array->total_size; + ping_id *= array->total_size; + ping_id += index; + + if (ping_id == 0) + ping_id += array->total_size; + + array->entries[index].ping_id = ping_id; + return ping_id; +} + + +/* Check if ping_id is valid and not timed out. + * + * On success, copies the data into data of length, + * + * return length of data copied on success. + * return -1 on failure. + */ +int ping_array_check(uint8_t *data, uint32_t length, Ping_Array *array, uint64_t ping_id) +{ + if (ping_id == 0) + return -1; + + uint32_t index = ping_id % array->total_size; + + if (array->entries[index].ping_id != ping_id) + return -1; + + if (is_timeout(array->entries[index].time, array->timeout)) + return -1; + + if (array->entries[index].length > length) + return -1; + + if (array->entries[index].data == NULL) + return -1; + + memcpy(data, array->entries[index].data, array->entries[index].length); + uint32_t len = array->entries[index].length; + clear_entry(array, index); + return len; +} + +/* Initialize a Ping_Array. + * size represents the total size of the array and should be a power of 2. + * timeout represents the maximum timeout in seconds for the entry. + * + * return 0 on success. + * return -1 on failure. + */ +int ping_array_init(Ping_Array *empty_array, uint32_t size, uint32_t timeout) +{ + if (size == 0 || timeout == 0 || empty_array == NULL) + return -1; + + empty_array->entries = malloc(size * sizeof(Ping_Array_Entry)); + + if (empty_array->entries == NULL) + return -1; + + empty_array->last_deleted = empty_array->last_added = 0; + empty_array->total_size = size; + empty_array->timeout = timeout; + return 0; +} + +/* Free all the allocated memory in a Ping_Array. + */ +void ping_array_free_all(Ping_Array *array) +{ + while (array->last_deleted != array->last_added) { + uint32_t index = array->last_deleted % array->total_size; + clear_entry(array, index); + ++array->last_deleted; + } + + free(array->entries); + array->entries = NULL; +} + diff --git a/toxcore/ping_array.h b/toxcore/ping_array.h new file mode 100644 index 00000000..b7fff1eb --- /dev/null +++ b/toxcore/ping_array.h @@ -0,0 +1,75 @@ +/* ping_array.h + * + * Implementation of an efficient array to store that we pinged something. + * + * Copyright (C) 2013 Tox project All Rights Reserved. + * + * This file is part of Tox. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see . + * + */ +#ifndef PING_ARRAY_H +#define PING_ARRAY_H + +#include "network.h" + +typedef struct { + void *data; + uint32_t length; + uint64_t time; + uint64_t ping_id; +} Ping_Array_Entry; + + +typedef struct { + Ping_Array_Entry *entries; + + uint32_t last_deleted; /* number representing the next entry to be deleted. */ + uint32_t last_added; /* number representing the last entry to be added. */ + uint32_t total_size; /* The length of entries */ + uint32_t timeout; /* The timeout after which entries are cleared. */ +} Ping_Array; + + +/* Add a data with length to the Ping_Array list and return a ping_id. + * + * return ping_id on success. + * return 0 on failure. + */ +uint64_t ping_array_add(Ping_Array *array, uint8_t *data, uint32_t length); + +/* Check if ping_id is valid and not timed out. + * + * On success, copies the data into data of length, + * + * return length of data copied on success. + * return -1 on failure. + */ +int ping_array_check(uint8_t *data, uint32_t length, Ping_Array *array, uint64_t ping_id); + +/* Initialize a Ping_Array. + * size represents the total size of the array and should be a power of 2. + * timeout represents the maximum timeout in seconds for the entry. + * + * return 0 on success. + * return -1 on failure. + */ +int ping_array_init(Ping_Array *empty_array, uint32_t size, uint32_t timeout); + +/* Free all the allocated memory in a Ping_Array. + */ +void ping_array_free_all(Ping_Array *array); + +#endif From 8783bea25ee366cfa3b1fa7c8930c2c2ffaef8fc Mon Sep 17 00:00:00 2001 From: irungentoo Date: Mon, 12 May 2014 14:39:12 -0400 Subject: [PATCH 068/117] Use ping_array to store onion announce information instead of sending over a huge cookie. This reduces the size of the onion announce packets by 100 bytes. --- toxcore/onion_announce.c | 6 ++--- toxcore/onion_announce.h | 4 +-- toxcore/onion_client.c | 53 +++++++++++++++++++--------------------- toxcore/onion_client.h | 3 +++ toxcore/ping_array.h | 2 +- 5 files changed, 34 insertions(+), 34 deletions(-) diff --git a/toxcore/onion_announce.c b/toxcore/onion_announce.c index abe72486..e6489a67 100644 --- a/toxcore/onion_announce.c +++ b/toxcore/onion_announce.c @@ -50,14 +50,14 @@ * return 0 on success. */ int send_announce_request(Networking_Core *net, Onion_Path *path, Node_format dest, uint8_t *public_key, - uint8_t *secret_key, uint8_t *ping_id, uint8_t *client_id, uint8_t *data_public_key, uint8_t *sendback_data) + uint8_t *secret_key, uint8_t *ping_id, uint8_t *client_id, uint8_t *data_public_key, uint64_t sendback_data) { 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, 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); + memcpy(plain + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES, &sendback_data, + sizeof(sendback_data)); uint8_t packet[ANNOUNCE_REQUEST_SIZE]; packet[0] = NET_PACKET_ANNOUNCE_REQUEST; random_nonce(packet + 1); diff --git a/toxcore/onion_announce.h b/toxcore/onion_announce.h index dff61e99..ea320998 100644 --- a/toxcore/onion_announce.h +++ b/toxcore/onion_announce.h @@ -29,7 +29,7 @@ #define ONION_ANNOUNCE_TIMEOUT 300 #define ONION_PING_ID_SIZE crypto_hash_sha256_BYTES -#define ONION_ANNOUNCE_SENDBACK_DATA_LENGTH (crypto_box_NONCEBYTES + sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port) + crypto_box_MACBYTES) +#define ONION_ANNOUNCE_SENDBACK_DATA_LENGTH (sizeof(uint64_t)) #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) @@ -76,7 +76,7 @@ typedef struct { * return 0 on success. */ int send_announce_request(Networking_Core *net, Onion_Path *path, Node_format dest, uint8_t *public_key, - uint8_t *secret_key, uint8_t *ping_id, uint8_t *client_id, uint8_t *data_public_key, uint8_t *sendback_data); + uint8_t *secret_key, uint8_t *ping_id, uint8_t *client_id, uint8_t *data_public_key, uint64_t sendback_data); /* Create and send an onion data request packet. * diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index 0a238b5f..18221320 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c @@ -28,6 +28,9 @@ #include "util.h" #include "LAN_discovery.h" +/* defines for the array size and + timeout for onion announce packets. */ +#define ANNOUNCE_ARRAY_SIZE 256 #define ANNOUNCE_TIMEOUT 10 /* Create a new path or use an old suitable one (if pathnum is valid) @@ -105,20 +108,15 @@ static uint32_t set_path_timeouts(Onion_Client *onion_c, uint32_t num, IP_Port s * return 0 on success * */ -static int new_sendback(Onion_Client *onion_c, uint32_t num, uint8_t *public_key, IP_Port ip_port, uint8_t *sendback) +static int new_sendback(Onion_Client *onion_c, uint32_t num, uint8_t *public_key, IP_Port ip_port, uint64_t *sendback) { - uint8_t plain[sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port)]; - uint64_t time = unix_time(); - random_nonce(sendback); - memcpy(plain, &num, sizeof(uint32_t)); - memcpy(plain + sizeof(uint32_t), &time, sizeof(uint64_t)); - memcpy(plain + sizeof(uint32_t) + sizeof(uint64_t), public_key, crypto_box_PUBLICKEYBYTES); - memcpy(plain + sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES, &ip_port, sizeof(IP_Port)); + uint8_t data[sizeof(uint32_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port)]; + memcpy(data, &num, sizeof(uint32_t)); + memcpy(data + sizeof(uint32_t), public_key, crypto_box_PUBLICKEYBYTES); + memcpy(data + sizeof(uint32_t) + crypto_box_PUBLICKEYBYTES, &ip_port, sizeof(IP_Port)); + *sendback = ping_array_add(&onion_c->announce_ping_array, data, sizeof(data)); - int len = encrypt_data_symmetric(onion_c->secret_symmetric_key, sendback, plain, sizeof(plain), - sendback + crypto_box_NONCEBYTES); - - if ((uint32_t)len + crypto_box_NONCEBYTES != ONION_ANNOUNCE_SENDBACK_DATA_LENGTH) + if (*sendback == 0) return -1; return 0; @@ -136,24 +134,17 @@ static int new_sendback(Onion_Client *onion_c, uint32_t num, uint8_t *public_key */ static uint32_t check_sendback(Onion_Client *onion_c, uint8_t *sendback, uint8_t *ret_pubkey, IP_Port *ret_ip_port) { - uint8_t plain[sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port)]; - int len = decrypt_data_symmetric(onion_c->secret_symmetric_key, sendback, sendback + crypto_box_NONCEBYTES, - ONION_ANNOUNCE_SENDBACK_DATA_LENGTH - crypto_box_NONCEBYTES, plain); + uint64_t sback; + memcpy(&sback, sendback, sizeof(uint64_t)); + uint8_t data[sizeof(uint32_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port)]; - if ((uint32_t)len != sizeof(plain)) + if (ping_array_check(data, sizeof(data), &onion_c->announce_ping_array, sback) != sizeof(data)) return ~0; - uint64_t timestamp; - memcpy(×tamp, plain + sizeof(uint32_t), sizeof(uint64_t)); - uint64_t temp_time = unix_time(); - - if (timestamp + ANNOUNCE_TIMEOUT < temp_time || temp_time < timestamp) - return ~0; - - memcpy(ret_pubkey, plain + sizeof(uint32_t) + sizeof(uint64_t), crypto_box_PUBLICKEYBYTES); - memcpy(ret_ip_port, plain + sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES, sizeof(IP_Port)); + memcpy(ret_pubkey, data + sizeof(uint32_t), crypto_box_PUBLICKEYBYTES); + memcpy(ret_ip_port, data + sizeof(uint32_t) + crypto_box_PUBLICKEYBYTES, sizeof(IP_Port)); uint32_t num; - memcpy(&num, plain, sizeof(uint32_t)); + memcpy(&num, data, sizeof(uint32_t)); return num; } @@ -163,9 +154,9 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_ if (num > onion_c->num_friends) return -1; - uint8_t sendback[ONION_ANNOUNCE_SENDBACK_DATA_LENGTH]; + uint64_t sendback; - if (new_sendback(onion_c, num, 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}; @@ -1010,6 +1001,11 @@ Onion_Client *new_onion_client(Net_Crypto *c) if (onion_c == NULL) return NULL; + if (ping_array_init(&onion_c->announce_ping_array, ANNOUNCE_ARRAY_SIZE, ANNOUNCE_TIMEOUT) != 0) { + free(onion_c); + return NULL; + } + onion_c->dht = c->dht; onion_c->net = c->dht->net; onion_c->c = c; @@ -1028,6 +1024,7 @@ void kill_onion_client(Onion_Client *onion_c) if (onion_c == NULL) return; + ping_array_free_all(&onion_c->announce_ping_array); realloc_onion_friends(onion_c, 0); networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, NULL, NULL); networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, NULL, NULL); diff --git a/toxcore/onion_client.h b/toxcore/onion_client.h index 32d2989f..06909380 100644 --- a/toxcore/onion_client.h +++ b/toxcore/onion_client.h @@ -26,6 +26,7 @@ #include "onion_announce.h" #include "net_crypto.h" +#include "ping_array.h" #define MAX_ONION_CLIENTS 8 #define ONION_NODE_PING_INTERVAL 30 @@ -124,6 +125,8 @@ typedef struct { uint32_t ping_nodes_sent_second; Last_Pinged last_pinged[MAX_STORED_PINGED_NODES]; + + Ping_Array announce_ping_array; uint8_t last_pinged_index; struct { oniondata_handler_callback function; diff --git a/toxcore/ping_array.h b/toxcore/ping_array.h index b7fff1eb..c5811b16 100644 --- a/toxcore/ping_array.h +++ b/toxcore/ping_array.h @@ -53,7 +53,7 @@ uint64_t ping_array_add(Ping_Array *array, uint8_t *data, uint32_t length); /* Check if ping_id is valid and not timed out. * * On success, copies the data into data of length, - * + * * return length of data copied on success. * return -1 on failure. */ From 53cc5ea6a9b31879443290993267da58f7404a85 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Mon, 12 May 2014 19:43:44 -0400 Subject: [PATCH 069/117] Fixed onion test. --- auto_tests/onion_test.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/auto_tests/onion_test.c b/auto_tests/onion_test.c index b8145cc2..4489a894 100644 --- a/auto_tests/onion_test.c +++ b/auto_tests/onion_test.c @@ -176,10 +176,12 @@ START_TEST(test_basic) ck_assert_msg((onion1_a != NULL) && (onion2_a != NULL), "Onion_Announce failed initializing."); uint8_t zeroes[64] = {0}; randombytes(sb_data, sizeof(sb_data)); + uint64_t s; + memcpy(&s, sb_data, sizeof(uint64_t)); memcpy(test_3_pub_key, nodes[3].client_id, crypto_box_PUBLICKEYBYTES); ret = send_announce_request(onion1->net, &path, nodes[3], onion1->dht->self_public_key, onion1->dht->self_secret_key, - zeroes, onion1->dht->self_public_key, onion1->dht->self_public_key, sb_data); + zeroes, onion1->dht->self_public_key, onion1->dht->self_public_key, s); ck_assert_msg(ret == 0, "Failed to create/send onion announce_request packet."); handled_test_3 = 0; @@ -190,11 +192,12 @@ START_TEST(test_basic) } randombytes(sb_data, sizeof(sb_data)); + memcpy(&s, sb_data, sizeof(uint64_t)); memcpy(onion2_a->entries[1].public_key, onion2->dht->self_public_key, crypto_box_PUBLICKEYBYTES); onion2_a->entries[1].time = unix_time(); networking_registerhandler(onion1->net, NET_PACKET_ONION_DATA_RESPONSE, &handle_test_4, onion1); send_announce_request(onion1->net, &path, nodes[3], onion1->dht->self_public_key, onion1->dht->self_secret_key, - test_3_ping_id, onion1->dht->self_public_key, onion1->dht->self_public_key, sb_data); + test_3_ping_id, onion1->dht->self_public_key, onion1->dht->self_public_key, s); while (memcmp(onion2_a->entries[ONION_ANNOUNCE_MAX_ENTRIES - 2].public_key, onion1->dht->self_public_key, crypto_box_PUBLICKEYBYTES) != 0) { From 5b58da35f94884db535c5e54164d3771ef2c0bc7 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Mon, 12 May 2014 19:48:19 -0400 Subject: [PATCH 070/117] Fixed segfault. --- toxcore/ping_array.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toxcore/ping_array.c b/toxcore/ping_array.c index cb18ceb3..e6f684ef 100644 --- a/toxcore/ping_array.c +++ b/toxcore/ping_array.c @@ -135,7 +135,7 @@ int ping_array_init(Ping_Array *empty_array, uint32_t size, uint32_t timeout) if (size == 0 || timeout == 0 || empty_array == NULL) return -1; - empty_array->entries = malloc(size * sizeof(Ping_Array_Entry)); + empty_array->entries = calloc(size * sizeof(Ping_Array_Entry), 1); if (empty_array->entries == NULL) return -1; From 2ea0657a6d37602357cf0c95c594a52f38273b12 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Mon, 12 May 2014 20:59:51 -0400 Subject: [PATCH 071/117] Fixed some issues. Friends with multiple ips (on LAN) should be handled better. Remade the function to check the crypto connection status. --- toxcore/Messenger.c | 25 ++++++++++++++----------- toxcore/net_crypto.c | 24 ++++++++++++++---------- toxcore/net_crypto.h | 10 ++++------ 3 files changed, 32 insertions(+), 27 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index ced1e845..267670f9 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -885,7 +885,12 @@ static IP_Port get_friend_ipport(Messenger *m, int32_t friendnumber) int crypt_id = m->friendlist[friendnumber].crypt_connection_id; - if (is_cryptoconnected(m->net_crypto, crypt_id) != CRYPTO_CONN_ESTABLISHED) + uint8_t direct_connected; + + if (crypto_connection_status(m->net_crypto, crypt_id, &direct_connected) != CRYPTO_CONN_ESTABLISHED) + return zero; + + if (direct_connected == 0) return zero; return m->net_crypto->crypto_connections[crypt_id].ip_port; @@ -2201,10 +2206,15 @@ void do_friends(Messenger *m) set_conection_dht_public_key(m->net_crypto, m->friendlist[i].crypt_connection_id, dht_public_key); } - IP_Port friendip; + uint8_t direct_connected; + unsigned int status = crypto_connection_status(m->net_crypto, m->friendlist[i].crypt_connection_id, &direct_connected); - if (onion_getfriendip(m->onion_c, m->friendlist[i].onion_friendnum, &friendip) == 1) { - set_direct_ip_port(m->net_crypto, m->friendlist[i].crypt_connection_id, friendip); + if (direct_connected == 0 || status == CRYPTO_CONN_COOKIE_REQUESTING) { + IP_Port friendip; + + if (onion_getfriendip(m->onion_c, m->friendlist[i].onion_friendnum, &friendip) == 1) { + set_direct_ip_port(m->net_crypto, m->friendlist[i].crypt_connection_id, friendip); + } } } @@ -2233,13 +2243,6 @@ void do_friends(Messenger *m) send_ping(m, i); } - if (is_cryptoconnected(m->net_crypto, - m->friendlist[i].crypt_connection_id) == CRYPTO_CONN_TIMED_OUT) { /* If the connection timed out, kill it. */ - crypto_kill(m->net_crypto, m->friendlist[i].crypt_connection_id); - m->friendlist[i].crypt_connection_id = -1; - set_friend_status(m, i, FRIEND_CONFIRMED); - } - if (m->friendlist[i].ping_lastrecv + FRIEND_CONNECTION_TIMEOUT < temp_time) { /* If we stopped receiving ping packets, kill it. */ crypto_kill(m->net_crypto, m->friendlist[i].crypt_connection_id); diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index a5149a7c..685ce653 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -1309,7 +1309,6 @@ int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c) if (create_send_handshake(c, crypt_connection_id, n_c->cookie) != 0) return -1; - send_temp_packet(c, crypt_connection_id); conn->status = CRYPTO_CONN_NOT_CONFIRMED; conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE; crypto_connection_add_source(c, crypt_connection_id, n_c->source); @@ -1651,18 +1650,23 @@ int crypto_kill(Net_Crypto *c, int crypt_connection_id) return wipe_crypto_connection(c, crypt_connection_id); } -/* return 0 if no connection. - * return 1 we have sent a handshake. - * return 2 if connection is not confirmed yet (we have received a handshake but no empty data packet). - * return 3 if the connection is established. - * return 4 if the connection is timed out and waiting to be killed. +/* return one of CRYPTO_CONN_* values indicating the state of the connection. + * + * sets direct_connected to 1 if connection connects directly to other, 0 if it isn't. */ -int is_cryptoconnected(Net_Crypto *c, int crypt_connection_id) +unsigned int crypto_connection_status(Net_Crypto *c, int crypt_connection_id, uint8_t *direct_connected) { - if ((unsigned int)crypt_connection_id < c->crypto_connections_length) - return c->crypto_connections[crypt_connection_id].status; + Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); - return CRYPTO_CONN_NO_CONNECTION; + if (conn == 0) + return CRYPTO_CONN_NO_CONNECTION; + + *direct_connected = 0; + + if ((CRYPTO_SEND_PACKET_INTERVAL * MAX_NUM_SENDPACKET_TRIES + conn->direct_lastrecv_time) > current_time_monotonic()) + *direct_connected = 1; + + return conn->status; } void new_keys(Net_Crypto *c) diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index 7d616be6..a010c4d2 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -235,13 +235,11 @@ int64_t write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, int crypto_kill(Net_Crypto *c, int crypt_connection_id); -/* return 0 if no connection. - * return 1 we have sent a handshake - * return 2 if connexion is not confirmed yet (we have received a handshake but no empty data packet). - * return 3 if the connection is established. - * return 4 if the connection is timed out and waiting to be killed. +/* return one of CRYPTO_CONN_* values indicating the state of the connection. + * + * sets direct_connected to 1 if connection connects directly to other, 0 if it isn't. */ -int is_cryptoconnected(Net_Crypto *c, int crypt_connection_id); +unsigned int crypto_connection_status(Net_Crypto *c, int crypt_connection_id, uint8_t *direct_connected); /* Generate our public and private keys. From 8d50e4a866731ddccd5fe54420b7a10e12e84327 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 13 May 2014 12:09:40 -0400 Subject: [PATCH 072/117] Fixed tox_test sometimes timing out. --- auto_tests/tox_test.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c index 5723d1c3..9b63b35b 100644 --- a/auto_tests/tox_test.c +++ b/auto_tests/tox_test.c @@ -292,6 +292,12 @@ START_TEST(test_many_clients) loop_top: pairs[i].tox1 = rand() % NUM_TOXES; pairs[i].tox2 = (pairs[i].tox1 + rand() % (NUM_TOXES - 1) + 1) % NUM_TOXES; + + for (j = 0; j < i; ++j) { + if (pairs[j].tox2 == pairs[i].tox1 && pairs[j].tox1 == pairs[i].tox2) + goto loop_top; + } + tox_get_address(toxes[pairs[i].tox1], address); int test = tox_add_friend(toxes[pairs[i].tox2], address, (uint8_t *)"Gentoo", 7); From a5ff3f8aff43a0f98592eb8b72b0db8671fe4354 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 13 May 2014 12:14:09 -0400 Subject: [PATCH 073/117] Nodes already in the DHT closelist should not be added to the toping list. --- toxcore/DHT.c | 2 +- toxcore/ping.c | 31 ++++++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/toxcore/DHT.c b/toxcore/DHT.c index 7678ae7f..9a5550dd 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c @@ -382,7 +382,7 @@ static int client_or_ip_port_in_list(Client_data *list, uint32_t length, uint8_t /* Check if client with client_id is already in node format list of length length. * * return 1 if true. - * return 2 if false. + * return 0 if false. */ static int client_in_nodelist(Node_format *list, uint32_t length, uint8_t *client_id) { diff --git a/toxcore/ping.c b/toxcore/ping.c index 52817cd6..2d16e354 100644 --- a/toxcore/ping.c +++ b/toxcore/ping.c @@ -42,7 +42,7 @@ #define MAX_TO_PING 8 /* Ping newly announced nodes to ping per TIME_TO_PING seconds*/ -#define TIME_TO_PING 3 +#define TIME_TO_PING 8 struct PING { @@ -201,6 +201,32 @@ static int handle_ping_response(void *_dht, IP_Port source, uint8_t *packet, uin return 0; } +/* Check if client_id with ip_port is in the list. + * + * return 1 if it is. + * return 0 if it isn't. + */ +static int in_list(Client_data *list, uint32_t length, uint8_t *client_id, IP_Port ip_port) +{ + uint32_t i; + + for (i = 0; i < length; ++i) { + if (id_equal(list[i].client_id, client_id)) { + IPPTsPng *ipptp; + + if (ip_port.ip.family == AF_INET) { + ipptp = &list[i].assoc4; + } else { + ipptp = &list[i].assoc6; + } + + if (!is_timeout(ipptp->timestamp, BAD_NODE_TIMEOUT) && ipport_equal(&ipptp->ip_port, &ip_port)) + return 1; + } + } + + return 0; +} /* Add nodes to the to_ping list. * All nodes in this list are pinged every TIME_TO_PING seconds @@ -217,6 +243,9 @@ int add_to_ping(PING *ping, uint8_t *client_id, IP_Port ip_port) if (!ip_isset(&ip_port.ip)) return -1; + if (in_list(ping->dht->close_clientlist, LCLIENT_LIST, client_id, ip_port)) + return -1; + uint32_t i; for (i = 0; i < MAX_TO_PING; ++i) { From a05ab89dbfa0ff3fe2f926dbc583e2c2964e9fa2 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 13 May 2014 14:53:59 -0400 Subject: [PATCH 074/117] pack/unpack nodes can now pack and unpack TCP nodes. --- toxcore/DHT.c | 63 ++++++++++++++++++++++++++++++++++++------ toxcore/DHT.h | 3 +- toxcore/onion_client.c | 4 +-- 3 files changed, 58 insertions(+), 12 deletions(-) diff --git a/toxcore/DHT.c b/toxcore/DHT.c index 9a5550dd..5d6992f1 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c @@ -205,24 +205,43 @@ int pack_nodes(uint8_t *data, uint16_t length, Node_format *nodes, uint16_t numb uint32_t i, packed_length = 0; for (i = 0; i < number; ++i) { + int ipv6 = -1; + uint8_t net_family; + if (nodes[i].ip_port.ip.family == AF_INET) { + ipv6 = 0; + net_family = TOX_AF_INET; + } else if (nodes[i].ip_port.ip.family == TCP_INET) { + ipv6 = 0; + net_family = TOX_TCP_INET; + } else if (nodes[i].ip_port.ip.family == AF_INET6) { + ipv6 = 1; + net_family = TOX_AF_INET6; + } else if (nodes[i].ip_port.ip.family == TCP_INET6) { + ipv6 = 1; + net_family = TOX_TCP_INET6; + } else { + return -1; + } + + if (ipv6 == 0) { uint32_t size = 1 + sizeof(IP4) + sizeof(uint16_t) + CLIENT_ID_SIZE; if (packed_length + size > length) return -1; - data[packed_length] = TOX_AF_INET; + data[packed_length] = net_family; memcpy(data + packed_length + 1, &nodes[i].ip_port.ip.ip4, sizeof(IP4)); memcpy(data + packed_length + 1 + sizeof(IP4), &nodes[i].ip_port.port, sizeof(uint16_t)); memcpy(data + packed_length + 1 + sizeof(IP4) + sizeof(uint16_t), nodes[i].client_id, CLIENT_ID_SIZE); packed_length += size; - } else if (nodes[i].ip_port.ip.family == AF_INET6) { + } else if (ipv6 == 1) { uint32_t size = 1 + sizeof(IP6) + sizeof(uint16_t) + CLIENT_ID_SIZE; if (packed_length + size > length) return -1; - data[packed_length] = TOX_AF_INET6; + data[packed_length] = net_family; memcpy(data + packed_length + 1, &nodes[i].ip_port.ip.ip6, sizeof(IP6)); memcpy(data + packed_length + 1 + sizeof(IP6), &nodes[i].ip_port.port, sizeof(uint16_t)); memcpy(data + packed_length + 1 + sizeof(IP6) + sizeof(uint16_t), nodes[i].client_id, CLIENT_ID_SIZE); @@ -237,35 +256,61 @@ int pack_nodes(uint8_t *data, uint16_t length, Node_format *nodes, uint16_t numb /* Unpack data of length into nodes of size max_num_nodes. * Put the length of the data processed in processed_data_len. + * tcp_enabled sets if TCP nodes are expected (true) or not (false). * * return number of unpacked nodes on success. * return -1 on failure. */ int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint16_t *processed_data_len, uint8_t *data, - uint16_t length) + uint16_t length, uint8_t tcp_enabled) { uint32_t num = 0, len_processed = 0; while (num < max_num_nodes && len_processed < length) { + int ipv6 = -1; + uint8_t host_family; + if (data[len_processed] == TOX_AF_INET) { + ipv6 = 0; + host_family = AF_INET; + } else if (data[len_processed] == TOX_TCP_INET) { + if (!tcp_enabled) + return -1; + + ipv6 = 0; + host_family = TCP_INET; + } else if (data[len_processed] == TOX_AF_INET6) { + ipv6 = 1; + host_family = AF_INET6; + } else if (data[len_processed] == TOX_TCP_INET6) { + if (!tcp_enabled) + return -1; + + ipv6 = 1; + host_family = TCP_INET6; + } else { + return -1; + } + + if (ipv6 == 0) { uint32_t size = 1 + sizeof(IP4) + sizeof(uint16_t) + CLIENT_ID_SIZE; if (len_processed + size > length) return -1; - nodes[num].ip_port.ip.family = AF_INET; + nodes[num].ip_port.ip.family = host_family; memcpy(&nodes[num].ip_port.ip.ip4, data + len_processed + 1, sizeof(IP4)); memcpy(&nodes[num].ip_port.port, data + len_processed + 1 + sizeof(IP4), sizeof(uint16_t)); memcpy(nodes[num].client_id, data + len_processed + 1 + sizeof(IP4) + sizeof(uint16_t), CLIENT_ID_SIZE); len_processed += size; ++num; - } else if (data[len_processed] == TOX_AF_INET6) { + } else if (ipv6 == 1) { uint32_t size = 1 + sizeof(IP6) + sizeof(uint16_t) + CLIENT_ID_SIZE; if (len_processed + size > length) return -1; - nodes[num].ip_port.ip.family = AF_INET6; + nodes[num].ip_port.ip.family = host_family; memcpy(&nodes[num].ip_port.ip.ip6, data + len_processed + 1, sizeof(IP6)); memcpy(&nodes[num].ip_port.port, data + len_processed + 1 + sizeof(IP6), sizeof(uint16_t)); memcpy(nodes[num].client_id, data + len_processed + 1 + sizeof(IP6) + sizeof(uint16_t), CLIENT_ID_SIZE); @@ -1156,7 +1201,7 @@ static int handle_sendnodes_core(void *object, IP_Port source, uint8_t *packet, return 1; uint16_t length_nodes = 0; - int num_nodes = unpack_nodes(plain_nodes, plain[0], &length_nodes, plain + 1, data_size); + int num_nodes = unpack_nodes(plain_nodes, plain[0], &length_nodes, plain + 1, data_size, 0); if (length_nodes != data_size) return 1; @@ -2048,7 +2093,7 @@ static int handle_hardening(void *object, IP_Port source, uint8_t *source_pubkey uint16_t length_nodes = length - 1 - CLIENT_ID_SIZE; Node_format nodes[MAX_SENT_NODES]; - int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, 0, packet + 1 + CLIENT_ID_SIZE, length_nodes); + int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, 0, packet + 1 + CLIENT_ID_SIZE, length_nodes, 0); /* TODO: MAX_SENT_NODES nodes should be returned at all times (right now we have a small network size so it could cause problems for testing and etc..) */ diff --git a/toxcore/DHT.h b/toxcore/DHT.h index d6514ee9..41fe99c9 100644 --- a/toxcore/DHT.h +++ b/toxcore/DHT.h @@ -147,12 +147,13 @@ int pack_nodes(uint8_t *data, uint16_t length, Node_format *nodes, uint16_t numb /* Unpack data of length into nodes of size max_num_nodes. * Put the length of the data processed in processed_data_len. + * tcp_enabled sets if TCP nodes are expected (true) or not (false). * * return number of unpacked nodes on success. * return -1 on failure. */ int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint16_t *processed_data_len, uint8_t *data, - uint16_t length); + uint16_t length, uint8_t tcp_enabled); /*----------------------------------------------------------------------------------*/ diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index 18221320..9c2bd93d 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c @@ -393,7 +393,7 @@ static int handle_announce_response(void *object, IP_Port source, uint8_t *packe if (len_nodes != 0) { Node_format nodes[MAX_SENT_NODES]; - int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, 0, plain + 1 + ONION_PING_ID_SIZE, len_nodes); + int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, 0, plain + 1 + ONION_PING_ID_SIZE, len_nodes, 0); if (num_nodes <= 0) return 1; @@ -485,7 +485,7 @@ static int handle_fakeid_announce(void *object, uint8_t *source_pubkey, uint8_t if (len_nodes != 0) { Node_format nodes[MAX_SENT_NODES]; int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, 0, data + 1 + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES, - len_nodes); + len_nodes, 0); if (num_nodes <= 0) return 1; From 6b1578af3dcdd31e8fd967d1dd83a336990402c1 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 13 May 2014 18:09:38 -0400 Subject: [PATCH 075/117] TCP_client callbacks now have a per connection number that can be set. --- toxcore/TCP_client.c | 36 +++++++++++++++++++++++++++++------- toxcore/TCP_client.h | 21 +++++++++++++++------ 2 files changed, 44 insertions(+), 13 deletions(-) diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c index 3745e14d..891c864f 100644 --- a/toxcore/TCP_client.c +++ b/toxcore/TCP_client.c @@ -189,8 +189,8 @@ void routing_response_handler(TCP_Client_Connection *con, int (*response_callbac con->response_callback_object = object; } -void routing_status_handler(TCP_Client_Connection *con, int (*status_callback)(void *object, uint8_t connection_id, - uint8_t status), void *object) +void routing_status_handler(TCP_Client_Connection *con, int (*status_callback)(void *object, uint32_t number, + uint8_t connection_id, uint8_t status), void *object) { con->status_callback = status_callback; con->status_callback_object = object; @@ -214,8 +214,27 @@ int send_data(TCP_Client_Connection *con, uint8_t con_id, uint8_t *data, uint16_ return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); } -void routing_data_handler(TCP_Client_Connection *con, int (*data_callback)(void *object, uint8_t connection_id, - uint8_t *data, uint16_t length), void *object) +/* Set the number that will be used as an argument in the callbacks related to con_id. + * + * When not set by this function, the number is ~0. + * + * return 0 on success. + * return -1 on failure. + */ +int set_tcp_connection_number(TCP_Client_Connection *con, uint8_t con_id, uint32_t number) +{ + if (con_id >= NUM_CLIENT_CONNECTIONS) + return -1; + + if (con->connections[con_id].status == 0) + return -1; + + con->connections[con_id].number = number; + return 0; +} + +void routing_data_handler(TCP_Client_Connection *con, int (*data_callback)(void *object, uint32_t number, + uint8_t connection_id, uint8_t *data, uint16_t length), void *object) { con->data_callback = data_callback; con->data_callback_object = object; @@ -350,6 +369,7 @@ static int handle_TCP_packet(TCP_Client_Connection *conn, uint8_t *data, uint16_ return -1; conn->connections[con_id].status = 1; + conn->connections[con_id].number = ~0; memcpy(conn->connections[con_id].public_key, data + 2, crypto_box_PUBLICKEYBYTES); if (conn->response_callback) @@ -373,7 +393,8 @@ static int handle_TCP_packet(TCP_Client_Connection *conn, uint8_t *data, uint16_ conn->connections[con_id].status = 2; if (conn->status_callback) - conn->status_callback(conn->status_callback_object, con_id, conn->connections[con_id].status); + conn->status_callback(conn->status_callback_object, conn->connections[con_id].number, con_id, + conn->connections[con_id].status); return 0; } @@ -393,7 +414,8 @@ static int handle_TCP_packet(TCP_Client_Connection *conn, uint8_t *data, uint16_ conn->connections[con_id].status = 1; if (conn->status_callback) - conn->status_callback(conn->status_callback_object, con_id, conn->connections[con_id].status); + conn->status_callback(conn->status_callback_object, conn->connections[con_id].number, con_id, + conn->connections[con_id].status); return 0; } @@ -438,7 +460,7 @@ static int handle_TCP_packet(TCP_Client_Connection *conn, uint8_t *data, uint16_ uint8_t con_id = data[0] - NUM_RESERVED_PORTS; if (conn->data_callback) - conn->data_callback(conn->data_callback_object, con_id, data + 1, length - 1); + conn->data_callback(conn->data_callback_object, conn->connections[con_id].number, con_id, data + 1, length - 1); } } diff --git a/toxcore/TCP_client.h b/toxcore/TCP_client.h index c2daaf9c..64678790 100644 --- a/toxcore/TCP_client.h +++ b/toxcore/TCP_client.h @@ -59,12 +59,13 @@ typedef struct { struct { uint8_t status; /* 0 if not used, 1 if other is offline, 2 if other is online. */ uint8_t public_key[crypto_box_PUBLICKEYBYTES]; + uint32_t number; } connections[NUM_CLIENT_CONNECTIONS]; int (*response_callback)(void *object, uint8_t connection_id, uint8_t *public_key); void *response_callback_object; - int (*status_callback)(void *object, uint8_t connection_id, uint8_t status); + int (*status_callback)(void *object, uint32_t number, uint8_t connection_id, uint8_t status); void *status_callback_object; - int (*data_callback)(void *object, uint8_t connection_id, uint8_t *data, uint16_t length); + int (*data_callback)(void *object, uint32_t number, uint8_t connection_id, uint8_t *data, uint16_t length); void *data_callback_object; int (*onion_callback)(void *object, uint8_t *data, uint16_t length); @@ -99,16 +100,24 @@ void onion_response_handler(TCP_Client_Connection *con, int (*onion_callback)(vo int send_routing_request(TCP_Client_Connection *con, uint8_t *public_key); void routing_response_handler(TCP_Client_Connection *con, int (*response_callback)(void *object, uint8_t connection_id, uint8_t *public_key), void *object); -void routing_status_handler(TCP_Client_Connection *con, int (*status_callback)(void *object, uint8_t connection_id, - uint8_t status), void *object); +void routing_status_handler(TCP_Client_Connection *con, int (*status_callback)(void *object, uint32_t number, + uint8_t connection_id, uint8_t status), void *object); +/* Set the number that will be used as an argument in the callbacks related to con_id. + * + * When not set by this function, the number is ~0. + * + * return 0 on success. + * return -1 on failure. + */ +int set_tcp_connection_number(TCP_Client_Connection *con, uint8_t con_id, uint32_t number); /* return 1 on success. * return 0 if could not send packet. * return -1 on failure. */ int send_data(TCP_Client_Connection *con, uint8_t con_id, uint8_t *data, uint16_t length); -void routing_data_handler(TCP_Client_Connection *con, int (*data_callback)(void *object, uint8_t connection_id, - uint8_t *data, uint16_t length), void *object); +void routing_data_handler(TCP_Client_Connection *con, int (*data_callback)(void *object, uint32_t number, + uint8_t connection_id, uint8_t *data, uint16_t length), void *object); #endif From c2523a3c67ef3b55edec140e5238dc01d1a83da3 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 13 May 2014 20:52:34 -0400 Subject: [PATCH 076/117] Fixed TCP_test. TCP_test now tests set_tcp_connection_number. --- auto_tests/TCP_test.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/auto_tests/TCP_test.c b/auto_tests/TCP_test.c index d0470d29..c521903d 100644 --- a/auto_tests/TCP_test.c +++ b/auto_tests/TCP_test.c @@ -296,31 +296,37 @@ static uint8_t response_callback_connection_id; static uint8_t response_callback_public_key[crypto_box_PUBLICKEYBYTES]; static int response_callback(void *object, uint8_t connection_id, uint8_t *public_key) { - if (object != (void *)1) - return 1; - + set_tcp_connection_number(object - 2, connection_id, 7); response_callback_connection_id = connection_id; memcpy(response_callback_public_key, public_key, crypto_box_PUBLICKEYBYTES); response_callback_good++; + return 0; } static int status_callback_good; static uint8_t status_callback_connection_id; static uint8_t status_callback_status; -static int status_callback(void *object, uint8_t connection_id, uint8_t status) +static int status_callback(void *object, uint32_t number, uint8_t connection_id, uint8_t status) { if (object != (void *)2) return 1; + if (number != 7) + return 1; + status_callback_connection_id = connection_id; status_callback_status = status; status_callback_good++; + return 0; } static int data_callback_good; -static int data_callback(void *object, uint8_t connection_id, uint8_t *data, uint16_t length) +static int data_callback(void *object, uint32_t number, uint8_t connection_id, uint8_t *data, uint16_t length) { if (object != (void *)3) return 1; + if (number != 7) + return 1; + if (length != 5) return 1; @@ -378,7 +384,7 @@ START_TEST(test_client) uint8_t f2_secret_key[crypto_box_SECRETKEYBYTES]; crypto_box_keypair(f2_public_key, f2_secret_key); TCP_Client_Connection *conn2 = new_TCP_connection(ip_port_tcp_s, self_public_key, f2_public_key, f2_secret_key); - routing_response_handler(conn, response_callback, (void *)1); + routing_response_handler(conn, response_callback, conn + 2); routing_status_handler(conn, status_callback, (void *)2); routing_data_handler(conn, data_callback, (void *)3); response_callback_good = status_callback_good = data_callback_good = 0; From 8afe4a4fd7c963c6e2375832a830437bc1a1620f Mon Sep 17 00:00:00 2001 From: irungentoo Date: Wed, 14 May 2014 06:30:05 -0400 Subject: [PATCH 077/117] Really fixed TCP_test. --- auto_tests/TCP_test.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/auto_tests/TCP_test.c b/auto_tests/TCP_test.c index c521903d..0fbffac2 100644 --- a/auto_tests/TCP_test.c +++ b/auto_tests/TCP_test.c @@ -296,7 +296,9 @@ static uint8_t response_callback_connection_id; static uint8_t response_callback_public_key[crypto_box_PUBLICKEYBYTES]; static int response_callback(void *object, uint8_t connection_id, uint8_t *public_key) { - set_tcp_connection_number(object - 2, connection_id, 7); + if (set_tcp_connection_number(object - 2, connection_id, 7) != 0) + return 1; + response_callback_connection_id = connection_id; memcpy(response_callback_public_key, public_key, crypto_box_PUBLICKEYBYTES); response_callback_good++; @@ -384,7 +386,7 @@ START_TEST(test_client) uint8_t f2_secret_key[crypto_box_SECRETKEYBYTES]; crypto_box_keypair(f2_public_key, f2_secret_key); TCP_Client_Connection *conn2 = new_TCP_connection(ip_port_tcp_s, self_public_key, f2_public_key, f2_secret_key); - routing_response_handler(conn, response_callback, conn + 2); + routing_response_handler(conn, response_callback, ((void *)conn) + 2); routing_status_handler(conn, status_callback, (void *)2); routing_data_handler(conn, data_callback, (void *)3); response_callback_good = status_callback_good = data_callback_good = 0; From 0b2c44a708a7559cd7e7332747a851d18ad1e322 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Wed, 14 May 2014 12:08:30 -0400 Subject: [PATCH 078/117] It's bad to have more than one path with the same first node in the same path array. --- toxcore/DHT.c | 2 ++ toxcore/onion_client.c | 41 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/toxcore/DHT.c b/toxcore/DHT.c index 5d6992f1..33802b61 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c @@ -2230,6 +2230,8 @@ static int random_node_fromlist(Client_data *list, uint16_t list_size, Node_form * return the number of nodes. * * NOTE:this is used to pick nodes for paths. + * + * TODO: remove the LAN stuff from this. */ uint16_t random_nodes_path(DHT *dht, Node_format *nodes, uint16_t max_num) { diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index 9c2bd93d..73726a59 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c @@ -33,6 +33,33 @@ #define ANNOUNCE_ARRAY_SIZE 256 #define ANNOUNCE_TIMEOUT 10 + +/* + * return -1 if nodes are suitable for creating a new path. + * return path number of already existing similar path if one already exists. + */ +static int is_path_used(Onion_Client_Paths *onion_paths, Node_format *nodes) +{ + uint32_t i; + + for (i = 0; i < NUMBER_ONION_PATHS; ++i) { + if (is_timeout(onion_paths->last_path_success[i], ONION_PATH_TIMEOUT)) { + continue; + } + + if (is_timeout(onion_paths->path_creation_time[i], ONION_PATH_MAX_LIFETIME)) { + continue; + } + + if (ipport_equal(&onion_paths->paths[i].ip_port1, &nodes[0].ip_port)) { + printf("bad\n"); + return i; + } + } + + return -1; +} + /* Create a new path or use an old suitable one (if pathnum is valid) * or a rondom one from onion_paths. * @@ -54,11 +81,17 @@ static int random_path(DHT *dht, Onion_Client_Paths *onion_paths, uint32_t pathn if (random_nodes_path(dht, nodes, 3) != 3) return -1; - if (create_onion_path(dht, &onion_paths->paths[pathnum], nodes) == -1) - return -1; + int n = is_path_used(onion_paths, nodes); - onion_paths->last_path_success[pathnum] = unix_time() + ONION_PATH_FIRST_TIMEOUT - ONION_PATH_TIMEOUT; - onion_paths->path_creation_time[pathnum] = unix_time(); + if (n == -1) { + if (create_onion_path(dht, &onion_paths->paths[pathnum], nodes) == -1) + return -1; + + onion_paths->last_path_success[pathnum] = unix_time() + ONION_PATH_FIRST_TIMEOUT - ONION_PATH_TIMEOUT; + onion_paths->path_creation_time[pathnum] = unix_time(); + } else { + pathnum = n; + } } memcpy(path, &onion_paths->paths[pathnum], sizeof(Onion_Path)); From c5559e192dc0a9afe76b3058cb1be756bc787f37 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Wed, 14 May 2014 17:15:43 -0400 Subject: [PATCH 079/117] Added OOB packets to the TCP client and server. --- auto_tests/TCP_test.c | 29 +++++++++++++++++++++++++++-- docs/TCP_Network.txt | 9 +++++++++ toxcore/TCP_client.c | 34 ++++++++++++++++++++++++++++++++++ toxcore/TCP_client.h | 11 +++++++++++ toxcore/TCP_server.c | 33 +++++++++++++++++++++++++++++++++ toxcore/TCP_server.h | 3 +++ toxcore/onion_client.c | 1 - 7 files changed, 117 insertions(+), 3 deletions(-) diff --git a/auto_tests/TCP_test.c b/auto_tests/TCP_test.c index 0fbffac2..29a9f518 100644 --- a/auto_tests/TCP_test.c +++ b/auto_tests/TCP_test.c @@ -340,6 +340,27 @@ static int data_callback(void *object, uint32_t number, uint8_t connection_id, u return 1; } +static int oob_data_callback_good; +static uint8_t oob_pubkey[crypto_box_PUBLICKEYBYTES]; +static int oob_data_callback(void *object, uint8_t *public_key, uint8_t *data, uint16_t length) +{ + if (object != (void *)4) + return 1; + + if (length != 5) + return 1; + + if (memcmp(public_key, oob_pubkey, crypto_box_PUBLICKEYBYTES) != 0) + return 1; + + if (data[0] == 1 && data[1] == 2 && data[2] == 3 && data[3] == 4 && data[4] == 5) { + oob_data_callback_good++; + return 0; + } + + return 1; +} + START_TEST(test_client) { unix_time_update(); @@ -389,7 +410,8 @@ START_TEST(test_client) routing_response_handler(conn, response_callback, ((void *)conn) + 2); routing_status_handler(conn, status_callback, (void *)2); routing_data_handler(conn, data_callback, (void *)3); - response_callback_good = status_callback_good = data_callback_good = 0; + oob_data_handler(conn, oob_data_callback, (void *)4); + oob_data_callback_good = response_callback_good = status_callback_good = data_callback_good = 0; c_sleep(50); do_TCP_connection(conn); do_TCP_connection(conn2); @@ -399,6 +421,9 @@ START_TEST(test_client) do_TCP_connection(conn); do_TCP_connection(conn2); c_sleep(50); + uint8_t data[5] = {1, 2, 3, 4, 5}; + memcpy(oob_pubkey, f2_public_key, crypto_box_PUBLICKEYBYTES); + send_oob_packet(conn2, f_public_key, data, 5); send_routing_request(conn, f2_public_key); send_routing_request(conn2, f_public_key); c_sleep(50); @@ -406,6 +431,7 @@ START_TEST(test_client) c_sleep(50); do_TCP_connection(conn); do_TCP_connection(conn2); + ck_assert_msg(oob_data_callback_good == 1, "oob callback not called"); ck_assert_msg(response_callback_good == 1, "response callback not called"); ck_assert_msg(memcmp(response_callback_public_key, f2_public_key, crypto_box_PUBLICKEYBYTES) == 0, "wrong public key"); ck_assert_msg(status_callback_good == 1, "status callback not called"); @@ -413,7 +439,6 @@ START_TEST(test_client) ck_assert_msg(status_callback_connection_id == response_callback_connection_id, "connection ids not equal"); c_sleep(50); do_TCP_server(tcp_s); - uint8_t data[5] = {1, 2, 3, 4, 5}; ck_assert_msg(send_data(conn2, 0, data, 5) == 1, "send data failed"); c_sleep(50); do_TCP_server(tcp_s); diff --git a/docs/TCP_Network.txt b/docs/TCP_Network.txt index 9841329c..4bc2d433 100644 --- a/docs/TCP_Network.txt +++ b/docs/TCP_Network.txt @@ -104,6 +104,10 @@ special ids and packets: [uint8_t id (4)][uint64_t ping_id (0 is invalid)] 5 - ping response (pong) [uint8_t id (5)][uint64_t ping_id (0 is invalid)] +6 - OOB send +[uint8_t id (6)][destination public key (32 bytes)][data] +7 - OOB recv +[uint8_t id (7)][senders public key (32 bytes)][data] 8 - onion packet (same format as initial onion packet (See: Prevent tracking.txt) but packet id is 8 instead of 128) 9 - onion packet response (same format as onion packet with id 142 but id is 9 @@ -140,6 +144,11 @@ If the server receives a ping packet he must respond with a ping response. The server will send a ping packet to clients every 30 seconds, they have 30 seconds to respond, if they don't the connection is deleted. +OOB send packets will be sent to the peer connected to the TCP server with the +destination public key as a OOB recv packet. The client sending this packet has +no way of knowing if the packet reached its destination. + + Client: Implementation details coming soon. diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c index 891c864f..4652b4a6 100644 --- a/toxcore/TCP_client.c +++ b/toxcore/TCP_client.c @@ -214,6 +214,23 @@ int send_data(TCP_Client_Connection *con, uint8_t con_id, uint8_t *data, uint16_ return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); } +/* return 1 on success. + * return 0 if could not send packet. + * return -1 on failure. + */ +int send_oob_packet(TCP_Client_Connection *con, uint8_t *public_key, uint8_t *data, uint16_t length) +{ + if (length == 0 || length > TCP_MAX_OOB_DATA_LENGTH) + return -1; + + uint8_t packet[1 + crypto_box_PUBLICKEYBYTES + length]; + packet[0] = TCP_PACKET_OOB_SEND; + memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES); + memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, data, length); + return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); +} + + /* Set the number that will be used as an argument in the callbacks related to con_id. * * When not set by this function, the number is ~0. @@ -240,6 +257,12 @@ void routing_data_handler(TCP_Client_Connection *con, int (*data_callback)(void con->data_callback_object = object; } +void oob_data_handler(TCP_Client_Connection *con, int (*oob_data_callback)(void *object, uint8_t *public_key, + uint8_t *data, uint16_t length), void *object) +{ + con->oob_data_callback = oob_data_callback; + con->oob_data_callback_object = object; +} /* return 1 on success. * return 0 if could not send packet. @@ -448,6 +471,17 @@ static int handle_TCP_packet(TCP_Client_Connection *conn, uint8_t *data, uint16_ } } + case TCP_PACKET_OOB_RECV: { + if (length <= 1 + crypto_box_PUBLICKEYBYTES) + return -1; + + if (conn->oob_data_callback) + conn->oob_data_callback(conn->oob_data_callback_object, data + 1, data + 1 + crypto_box_PUBLICKEYBYTES, + length - (1 + crypto_box_PUBLICKEYBYTES)); + + return 0; + } + case TCP_PACKET_ONION_RESPONSE: { conn->onion_callback(conn->onion_callback_object, data + 1, length - 1); return 0; diff --git a/toxcore/TCP_client.h b/toxcore/TCP_client.h index 64678790..277378b9 100644 --- a/toxcore/TCP_client.h +++ b/toxcore/TCP_client.h @@ -67,6 +67,8 @@ typedef struct { void *status_callback_object; int (*data_callback)(void *object, uint32_t number, uint8_t connection_id, uint8_t *data, uint16_t length); void *data_callback_object; + int (*oob_data_callback)(void *object, uint8_t *public_key, uint8_t *data, uint16_t length); + void *oob_data_callback_object; int (*onion_callback)(void *object, uint8_t *data, uint16_t length); void *onion_callback_object; @@ -120,4 +122,13 @@ int send_data(TCP_Client_Connection *con, uint8_t con_id, uint8_t *data, uint16_ void routing_data_handler(TCP_Client_Connection *con, int (*data_callback)(void *object, uint32_t number, uint8_t connection_id, uint8_t *data, uint16_t length), void *object); +/* return 1 on success. + * return 0 if could not send packet. + * return -1 on failure. + */ +int send_oob_packet(TCP_Client_Connection *con, uint8_t *public_key, uint8_t *data, uint16_t length); +void oob_data_handler(TCP_Client_Connection *con, int (*oob_data_callback)(void *object, uint8_t *public_key, + uint8_t *data, uint16_t length), void *object); + + #endif diff --git a/toxcore/TCP_server.c b/toxcore/TCP_server.c index 79a420d3..914317b7 100644 --- a/toxcore/TCP_server.c +++ b/toxcore/TCP_server.c @@ -508,6 +508,31 @@ static int handle_TCP_routing_req(TCP_Server *TCP_server, uint32_t con_id, uint8 return 0; } +/* return 0 on success. + * return -1 on failure (connection must be killed). + */ +static int handle_TCP_oob_send(TCP_Server *TCP_server, uint32_t con_id, uint8_t *public_key, uint8_t *data, + uint16_t length) +{ + if (length == 0 || length > TCP_MAX_OOB_DATA_LENGTH) + return -1; + + TCP_Secure_Connection *con = &TCP_server->accepted_connection_array[con_id]; + + int other_index = get_TCP_connection_index(TCP_server, public_key); + + if (other_index != -1) { + uint8_t resp_packet[1 + crypto_box_PUBLICKEYBYTES + length]; + resp_packet[0] = TCP_PACKET_OOB_RECV; + memcpy(resp_packet + 1, con->public_key, crypto_box_PUBLICKEYBYTES); + memcpy(resp_packet + 1 + crypto_box_PUBLICKEYBYTES, data, length); + write_packet_TCP_secure_connection(&TCP_server->accepted_connection_array[other_index], resp_packet, + sizeof(resp_packet)); + } + + return 0; +} + static int disconnect_conection_index(TCP_Server *TCP_server, TCP_Secure_Connection *con, uint8_t con_number) { if (con_number >= NUM_CLIENT_CONNECTIONS) @@ -624,6 +649,14 @@ static int handle_TCP_packet(TCP_Server *TCP_server, uint32_t con_id, uint8_t *d } } + case TCP_PACKET_OOB_SEND: { + if (length <= 1 + crypto_box_PUBLICKEYBYTES) + return -1; + + return handle_TCP_oob_send(TCP_server, con_id, data + 1, data + 1 + crypto_box_PUBLICKEYBYTES, + length - (1 + crypto_box_PUBLICKEYBYTES)); + } + case TCP_PACKET_ONION_REQUEST: { if (TCP_server->onion) { if (length <= 1 + crypto_box_NONCEBYTES + ONION_SEND_BASE * 2) diff --git a/toxcore/TCP_server.h b/toxcore/TCP_server.h index 2a6b8276..136231d0 100644 --- a/toxcore/TCP_server.h +++ b/toxcore/TCP_server.h @@ -39,6 +39,7 @@ #define TCP_HANDSHAKE_PLAIN_SIZE (crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES) #define TCP_SERVER_HANDSHAKE_SIZE (crypto_box_NONCEBYTES + TCP_HANDSHAKE_PLAIN_SIZE + crypto_box_MACBYTES) #define TCP_CLIENT_HANDSHAKE_SIZE (crypto_box_PUBLICKEYBYTES + TCP_SERVER_HANDSHAKE_SIZE) +#define TCP_MAX_OOB_DATA_LENGTH 1024 #define NUM_RESERVED_PORTS 16 #define NUM_CLIENT_CONNECTIONS (256 - NUM_RESERVED_PORTS) @@ -49,6 +50,8 @@ #define TCP_PACKET_DISCONNECT_NOTIFICATION 3 #define TCP_PACKET_PING 4 #define TCP_PACKET_PONG 5 +#define TCP_PACKET_OOB_SEND 6 +#define TCP_PACKET_OOB_RECV 7 #define TCP_PACKET_ONION_REQUEST 8 #define TCP_PACKET_ONION_RESPONSE 9 diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index 73726a59..73cb1f75 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c @@ -52,7 +52,6 @@ static int is_path_used(Onion_Client_Paths *onion_paths, Node_format *nodes) } if (ipport_equal(&onion_paths->paths[i].ip_port1, &nodes[0].ip_port)) { - printf("bad\n"); return i; } } From 1e7164fcee879a4392ccb45c80607bd5b5c71352 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 15 May 2014 16:49:39 -0400 Subject: [PATCH 080/117] Fixed possibility that packet_send_rate would get stuck. --- toxcore/net_crypto.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 685ce653..41efc1b1 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -1549,15 +1549,15 @@ static void send_crypto_packets(Net_Crypto *c) if ((double)num_packets_array(&conn->send_array) < 0.3 * (conn->packet_send_rate)) { conn->packet_send_rate *= 1.2; - } else if ((double)num_packets_array(&conn->send_array) > 0.5 * (conn->packet_send_rate)) { + } else if ((double)num_packets_array(&conn->send_array) > 0.4 * (conn->packet_send_rate)) { conn->packet_send_rate *= 0.8; } if (conn->packet_send_rate < CRYPTO_PACKET_MIN_RATE || !conn->sending) conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE; - if (conn->packet_send_rate > CRYPTO_PACKET_BUFFER_SIZE * 8) - conn->packet_send_rate = CRYPTO_PACKET_BUFFER_SIZE * 8; + if (conn->packet_send_rate > CRYPTO_PACKET_BUFFER_SIZE * 2) + conn->packet_send_rate = CRYPTO_PACKET_BUFFER_SIZE * 2; } From a5141679527b10de8cc6e0aa211873706abac149 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 15 May 2014 20:57:55 -0400 Subject: [PATCH 081/117] Exposed and tested disconnect notification TCP packets. --- auto_tests/TCP_test.c | 9 +++++++++ toxcore/TCP_client.c | 15 +++++++++++++++ toxcore/TCP_client.h | 6 ++++++ 3 files changed, 30 insertions(+) diff --git a/auto_tests/TCP_test.c b/auto_tests/TCP_test.c index 29a9f518..ca5afd9a 100644 --- a/auto_tests/TCP_test.c +++ b/auto_tests/TCP_test.c @@ -446,6 +446,15 @@ START_TEST(test_client) do_TCP_connection(conn); do_TCP_connection(conn2); ck_assert_msg(data_callback_good == 1, "data callback not called"); + status_callback_good = 0; + send_disconnect_request(conn2, 0); + c_sleep(50); + do_TCP_server(tcp_s); + c_sleep(50); + do_TCP_connection(conn); + do_TCP_connection(conn2); + ck_assert_msg(status_callback_good == 1, "status callback not called"); + ck_assert_msg(status_callback_status == 1, "wrong status"); } END_TEST diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c index 4652b4a6..209c1775 100644 --- a/toxcore/TCP_client.c +++ b/toxcore/TCP_client.c @@ -300,6 +300,20 @@ static int send_ping_response(TCP_Client_Connection *con, uint64_t ping_id) return write_packet_TCP_secure_connection(con, packet, sizeof(packet)); } +/* return 1 on success. + * return 0 if could not send packet. + * return -1 on failure (connection must be killed). + */ +int send_disconnect_request(TCP_Client_Connection *con, uint8_t con_id) +{ + if (con_id >= NUM_CLIENT_CONNECTIONS) + return -1; + + con->connections[con_id].status = 0; + con->connections[con_id].number = 0; + return send_disconnect_notification(con, con_id + NUM_RESERVED_PORTS); +} + /* return 1 on success. * return 0 if could not send packet. * return -1 on failure (connection must be killed). @@ -564,6 +578,7 @@ void do_TCP_connection(TCP_Client_Connection *TCP_connection) if (sizeof(data) == len) { if (handle_handshake(TCP_connection, data) == 0) { + TCP_connection->kill_at = ~0; TCP_connection->status = TCP_CLIENT_CONFIRMED; } else { TCP_connection->kill_at = 0; diff --git a/toxcore/TCP_client.h b/toxcore/TCP_client.h index 277378b9..768ef9d2 100644 --- a/toxcore/TCP_client.h +++ b/toxcore/TCP_client.h @@ -105,6 +105,12 @@ void routing_response_handler(TCP_Client_Connection *con, int (*response_callbac void routing_status_handler(TCP_Client_Connection *con, int (*status_callback)(void *object, uint32_t number, uint8_t connection_id, uint8_t status), void *object); +/* return 1 on success. + * return 0 if could not send packet. + * return -1 on failure (connection must be killed). + */ +int send_disconnect_request(TCP_Client_Connection *con, uint8_t con_id); + /* Set the number that will be used as an argument in the callbacks related to con_id. * * When not set by this function, the number is ~0. From 297281dea5166aa2dd12fd98e9148562645d4725 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 16 May 2014 11:26:41 -0400 Subject: [PATCH 082/117] Fixed some issues in TCP_server. Timed out connections now remove themselves correctly. If a peer with the same public key as another tries to connect, the old connection is killed. --- toxcore/TCP_server.c | 94 ++++++++++++++++++++++++++++---------------- toxcore/TCP_server.h | 2 +- 2 files changed, 61 insertions(+), 35 deletions(-) diff --git a/toxcore/TCP_server.c b/toxcore/TCP_server.c index 914317b7..ec8dbf1a 100644 --- a/toxcore/TCP_server.c +++ b/toxcore/TCP_server.c @@ -84,6 +84,25 @@ static int realloc_connection(TCP_Server *TCP_server, uint32_t num) return 0; } +/* return index corresponding to connection with peer on success + * return -1 on failure. + */ +static int get_TCP_connection_index(TCP_Server *TCP_server, uint8_t *public_key) +{ + //TODO optimize this function. + uint32_t i; + + for (i = 0; i < TCP_server->size_accepted_connections; ++i) { + if (memcmp(TCP_server->accepted_connection_array[i].public_key, public_key, crypto_box_PUBLICKEYBYTES) == 0) + return i; + } + + return -1; +} + + +static int kill_accepted(TCP_Server *TCP_server, int index); + /* Add accepted TCP connection to the list. * * return index on success @@ -91,7 +110,12 @@ static int realloc_connection(TCP_Server *TCP_server, uint32_t num) */ static int add_accepted(TCP_Server *TCP_server, TCP_Secure_Connection *con) { - int index = -1; + int index = get_TCP_connection_index(TCP_server, con->public_key); + + if (index != -1) { /* If an old connection to the same public key exists, kill it. */ + kill_accepted(TCP_server, index); + index = -1; + } if (TCP_server->size_accepted_connections == TCP_server->num_accepted_connections) { if (realloc_connection(TCP_server, TCP_server->size_accepted_connections + 4) == -1) @@ -145,22 +169,6 @@ static int del_accepted(TCP_Server *TCP_server, int index) return 0; } -/* return index corresponding to connection with peer on success - * return -1 on failure. - */ -static int get_TCP_connection_index(TCP_Server *TCP_server, uint8_t *public_key) -{ - //TODO optimize this function. - uint32_t i; - - for (i = 0; i < TCP_server->size_accepted_connections; ++i) { - if (memcmp(TCP_server->accepted_connection_array[i].public_key, public_key, crypto_box_PUBLICKEYBYTES) == 0) - return i; - } - - return -1; -} - /* Read the next two bytes in TCP stream then convert them to * length (host byte order). * @@ -342,6 +350,25 @@ static void kill_TCP_connection(TCP_Secure_Connection *con) memset(con, 0, sizeof(TCP_Secure_Connection)); } +/* Kill an accepted TCP_Secure_Connection + * + * return -1 on failure. + * return 0 on success. + */ +static int kill_accepted(TCP_Server *TCP_server, int index) +{ + if ((uint32_t)index >= TCP_server->size_accepted_connections) + return -1; + + sock_t sock = TCP_server->accepted_connection_array[index].sock; + + if (del_accepted(TCP_server, index) != 0) + return -1; + + kill_sock(sock); + return 0; +} + /* return 1 if everything went well. * return -1 if the connection must be killed. */ @@ -681,22 +708,22 @@ static int handle_TCP_packet(TCP_Server *TCP_server, uint32_t con_id, uint8_t *d if (data[0] < NUM_RESERVED_PORTS) return -1; - uint8_t con_id = data[0] - NUM_RESERVED_PORTS; + uint8_t c_id = data[0] - NUM_RESERVED_PORTS; - if (con_id >= NUM_CLIENT_CONNECTIONS) + if (c_id >= NUM_CLIENT_CONNECTIONS) return -1; - if (con->connections[con_id].status == 0) + if (con->connections[c_id].status == 0) return -1; - if (con->connections[con_id].status != 2) + if (con->connections[c_id].status != 2) return 0; - uint32_t index = con->connections[con_id].index; - uint8_t other_con_id = con->connections[con_id].other_id + NUM_RESERVED_PORTS; + uint32_t index = con->connections[c_id].index; + uint8_t other_c_id = con->connections[c_id].other_id + NUM_RESERVED_PORTS; uint8_t new_data[length]; memcpy(new_data, data, length); - new_data[0] = other_con_id; + new_data[0] = other_c_id; int ret = write_packet_TCP_secure_connection(&TCP_server->accepted_connection_array[index], new_data, length); if (ret == -1) @@ -717,11 +744,8 @@ static int confirm_TCP_connection(TCP_Server *TCP_server, TCP_Secure_Connection if (index == -1) return -1; - TCP_Secure_Connection *conn = &TCP_server->accepted_connection_array[index]; - if (handle_TCP_packet(TCP_server, index, data, length) == -1) { - kill_TCP_connection(conn); - del_accepted(TCP_server, index); + kill_accepted(TCP_server, index); } return 0; @@ -934,12 +958,16 @@ static void do_TCP_confirmed(TCP_Server *TCP_server) if (ret == 1) { conn->last_pinged = unix_time(); conn->ping_id = ping_id; + } else { + if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY + TCP_PING_TIMEOUT)) { + kill_accepted(TCP_server, i); + continue; + } } } if (conn->ping_id && is_timeout(conn->last_pinged, TCP_PING_TIMEOUT)) { - kill_TCP_connection(conn); - del_accepted(TCP_server, i); + kill_accepted(TCP_server, i); continue; } @@ -950,14 +978,12 @@ static void do_TCP_confirmed(TCP_Server *TCP_server) while ((len = read_packet_TCP_secure_connection(conn->sock, &conn->next_packet_length, conn->shared_key, conn->recv_nonce, packet, sizeof(packet)))) { if (len == -1) { - kill_TCP_connection(conn); - del_accepted(TCP_server, i); + kill_accepted(TCP_server, i); break; } if (handle_TCP_packet(TCP_server, i, packet, len) == -1) { - kill_TCP_connection(conn); - del_accepted(TCP_server, i); + kill_accepted(TCP_server, i); break; } } diff --git a/toxcore/TCP_server.h b/toxcore/TCP_server.h index 136231d0..fc8c234b 100644 --- a/toxcore/TCP_server.h +++ b/toxcore/TCP_server.h @@ -59,7 +59,7 @@ /* frequency to ping connected nodes and timeout in seconds */ #define TCP_PING_FREQUENCY 30 -#define TCP_PING_TIMEOUT 20 +#define TCP_PING_TIMEOUT 10 enum { TCP_STATUS_NO_STATUS, From cda3cedd37fd66d23362e326562ec666e51dc6fd Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 16 May 2014 12:43:53 -0400 Subject: [PATCH 083/117] TCP_server fix. Clear the connections array when connection is killed. Don't allow duplicate entries in connections array. --- toxcore/TCP_server.c | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/toxcore/TCP_server.c b/toxcore/TCP_server.c index ec8dbf1a..8be22593 100644 --- a/toxcore/TCP_server.c +++ b/toxcore/TCP_server.c @@ -350,6 +350,8 @@ static void kill_TCP_connection(TCP_Secure_Connection *con) memset(con, 0, sizeof(TCP_Secure_Connection)); } +static int rm_connection_index(TCP_Server *TCP_server, TCP_Secure_Connection *con, uint8_t con_number); + /* Kill an accepted TCP_Secure_Connection * * return -1 on failure. @@ -360,6 +362,12 @@ static int kill_accepted(TCP_Server *TCP_server, int index) if ((uint32_t)index >= TCP_server->size_accepted_connections) return -1; + uint32_t i; + + for (i = 0; i < NUM_CLIENT_CONNECTIONS; ++i) { + rm_connection_index(TCP_server, &TCP_server->accepted_connection_array[index], i); + } + sock_t sock = TCP_server->accepted_connection_array[index].sock; if (del_accepted(TCP_server, index) != 0) @@ -482,9 +490,16 @@ static int handle_TCP_routing_req(TCP_Server *TCP_server, uint32_t con_id, uint8 } for (i = 0; i < NUM_CLIENT_CONNECTIONS; ++i) { - if (con->connections[i].status == 0) { + if (con->connections[i].status != 0) { + if (memcmp(public_key, con->connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) { + if (send_routing_response(con, i + NUM_RESERVED_PORTS, public_key) == -1) { + return -1; + } else { + return 0; + } + } + } else if (index == (uint32_t)~0) { index = i; - break; } } @@ -560,7 +575,12 @@ static int handle_TCP_oob_send(TCP_Server *TCP_server, uint32_t con_id, uint8_t return 0; } -static int disconnect_conection_index(TCP_Server *TCP_server, TCP_Secure_Connection *con, uint8_t con_number) +/* Remove connection with con_number from the connections array of con. + * + * return -1 on failure. + * return 0 on success. + */ +static int rm_connection_index(TCP_Server *TCP_server, TCP_Secure_Connection *con, uint8_t con_number) { if (con_number >= NUM_CLIENT_CONNECTIONS) return -1; @@ -584,14 +604,21 @@ static int disconnect_conection_index(TCP_Server *TCP_server, TCP_Secure_Connect con->connections[con_number].index = 0; con->connections[con_number].other_id = 0; con->connections[con_number].status = 0; - //TODO: return values? - send_disconnect_notification(con, con_number); return 0; } else { return -1; } } +static int disconnect_conection_index(TCP_Server *TCP_server, TCP_Secure_Connection *con, uint8_t con_number) +{ + if (rm_connection_index(TCP_server, con, con_number) != 0) + return -1; + + send_disconnect_notification(con, con_number); + return 0; +} + static int handle_onion_recv_1(void *object, IP_Port dest, uint8_t *data, uint16_t length) { TCP_Server *TCP_server = object; From 1f7d8b71f01507623e2ff44e8e815a0a0aec105a Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 16 May 2014 13:42:19 -0400 Subject: [PATCH 084/117] Fixed TCP_client connections not timing out correctly. --- toxcore/TCP_client.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c index 209c1775..9091900f 100644 --- a/toxcore/TCP_client.c +++ b/toxcore/TCP_client.c @@ -532,6 +532,10 @@ static int do_confirmed_TCP(TCP_Client_Connection *conn) if (ret == 1) { conn->last_pinged = unix_time(); conn->ping_id = ping_id; + } else { + if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY + TCP_PING_TIMEOUT)) { + conn->status = TCP_CLIENT_DISCONNECTED; + } } } From 933428b89971216eb0650f77f15d0690a25067f0 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 16 May 2014 14:09:46 -0400 Subject: [PATCH 085/117] Removed non spec behaviour. --- toxcore/TCP_server.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/toxcore/TCP_server.c b/toxcore/TCP_server.c index 8be22593..31884604 100644 --- a/toxcore/TCP_server.c +++ b/toxcore/TCP_server.c @@ -610,15 +610,6 @@ static int rm_connection_index(TCP_Server *TCP_server, TCP_Secure_Connection *co } } -static int disconnect_conection_index(TCP_Server *TCP_server, TCP_Secure_Connection *con, uint8_t con_number) -{ - if (rm_connection_index(TCP_server, con, con_number) != 0) - return -1; - - send_disconnect_notification(con, con_number); - return 0; -} - static int handle_onion_recv_1(void *object, IP_Port dest, uint8_t *data, uint16_t length) { TCP_Server *TCP_server = object; @@ -671,7 +662,7 @@ static int handle_TCP_packet(TCP_Server *TCP_server, uint32_t con_id, uint8_t *d if (length != 2) return -1; - return disconnect_conection_index(TCP_server, con, data[1] - NUM_RESERVED_PORTS); + return rm_connection_index(TCP_server, con, data[1] - NUM_RESERVED_PORTS); } case TCP_PACKET_PING: { From 3ab05b6e2ed9392e20ec711b835b6a1f20980c0a Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 16 May 2014 17:29:50 -0400 Subject: [PATCH 086/117] Some TCP code added to net_crypto. add_tcp_relay() can be used to connect to some TCP relays. If both Toxes are connected to the same TCP relay(s) and create a connection on which they set the others dht_public_key, they will connect. --- toxcore/TCP_client.h | 2 + toxcore/net_crypto.c | 375 ++++++++++++++++++++++++++++++++++++++++++- toxcore/net_crypto.h | 15 +- 3 files changed, 388 insertions(+), 4 deletions(-) diff --git a/toxcore/TCP_client.h b/toxcore/TCP_client.h index 768ef9d2..9583e15f 100644 --- a/toxcore/TCP_client.h +++ b/toxcore/TCP_client.h @@ -56,6 +56,8 @@ typedef struct { uint64_t last_pinged; uint64_t ping_id; + void *net_crypto_pointer; + uint32_t net_crypto_location; struct { uint8_t status; /* 0 if not used, 1 if other is offline, 2 if other is online. */ uint8_t public_key[crypto_box_PUBLICKEYBYTES]; diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 41efc1b1..56ff1bdd 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -210,6 +210,28 @@ static int udp_handle_cookie_request(void *object, IP_Port source, uint8_t *pack return 0; } +/* Handle the cookie request packet (for TCP) + */ +static int tcp_handle_cookie_request(Net_Crypto *c, TCP_Client_Connection *TCP_con, uint8_t conn_id, uint8_t *packet, + uint32_t length) +{ + uint8_t request_plain[COOKIE_REQUEST_PLAIN_LENGTH]; + uint8_t shared_key[crypto_box_BEFORENMBYTES]; + + if (handle_cookie_request(c, request_plain, shared_key, packet, length) != 0) + return -1; + + uint8_t data[COOKIE_RESPONSE_LENGTH]; + + if (create_cookie_response(c, data, request_plain, shared_key) != sizeof(data)) + return -1; + + if ((uint32_t)send_data(TCP_con, conn_id, data, sizeof(data)) != 1) + return -1; + + return 0; +} + /* Handle a cookie response packet of length encrypted with shared_key. * put the cookie in the response in cookie * @@ -352,10 +374,23 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, uint8_t *data, if (conn == 0) return -1; - if ((uint32_t)sendpacket(c->dht->net, conn->ip_port, data, length) != length) - return -1; + //TODO: on bad networks, direct connections might not last indefinitely. + if (conn->ip_port.ip.family != 0) { + if ((uint32_t)sendpacket(c->dht->net, conn->ip_port, data, length) == length) + return 0; + } - return 0; + //TODO: spread packets over many relays, detect and kill bad relays. + uint32_t i; + + for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { + if (conn->status_tcp[i] == 2) {/* friend is connected to this relay. */ + if (send_data(c->tcp_connections[i], conn->con_number_tcp[i], data, length) == 1) + return 0; + } + } + + return -1; } /** START: Array Related functions **/ @@ -1187,6 +1222,24 @@ static int getcryptconnection_id(Net_Crypto *c, uint8_t *public_key) return -1; } +/* Get crypto connection id from public key of peer. + * + * return -1 if there are no connections like we are looking for. + * return id if it found it. + */ +static int getcryptconnection_id_dht_pubkey(Net_Crypto *c, uint8_t *dht_public_key) +{ + uint32_t i; + + for (i = 0; i < c->crypto_connections_length; ++i) { + if (c->crypto_connections[i].status != CRYPTO_CONN_NO_CONNECTION && c->crypto_connections[i].dht_public_key_set) + if (memcmp(dht_public_key, c->crypto_connections[i].dht_public_key, crypto_box_PUBLICKEYBYTES) == 0) + return i; + } + + return -1; +} + /* Add a source to the crypto connection. * This is to be used only when we have recieved a packet from that source. * @@ -1346,6 +1399,56 @@ int new_crypto_connection(Net_Crypto *c, uint8_t *real_public_key) return crypt_connection_id; } +/* Disconnect peer from all associated TCP connections. + * + * return -1 on failure. + * return 0 on success. + */ +static int disconnect_peer_tcp(Net_Crypto *c, int crypt_connection_id) +{ + Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); + + if (conn == 0) + return -1; + + uint32_t i; + + for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { + if (conn->status_tcp[i]) { + send_disconnect_request(c->tcp_connections[i], conn->con_number_tcp[i]); + conn->status_tcp[i] = 0; + conn->con_number_tcp[i] = 0; + } + } + + return 0; +} + +/* Connect peer to all associated TCP connections. + * + * return -1 on failure. + * return 0 on success. + */ +static int connect_peer_tcp(Net_Crypto *c, int crypt_connection_id) +{ + Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); + + if (conn == 0) + return -1; + + uint32_t i; + + for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { + if (c->tcp_connections[i] == NULL) + continue; + + //TODO check function return? + send_routing_request(c->tcp_connections[i], conn->dht_public_key); + } + + return 0; +} + /* Set the DHT public key of the crypto connection. * * return -1 on failure. @@ -1361,6 +1464,10 @@ int set_conection_dht_public_key(Net_Crypto *c, int crypt_connection_id, uint8_t if (conn->dht_public_key_set == 1 && memcmp(conn->dht_public_key, dht_public_key, crypto_box_PUBLICKEYBYTES) == 0) return -1; + if (conn->dht_public_key_set == 1) { + disconnect_peer_tcp(c, crypt_connection_id); + } + memcpy(conn->dht_public_key, dht_public_key, crypto_box_PUBLICKEYBYTES); conn->dht_public_key_set = 1; @@ -1376,6 +1483,7 @@ int set_conection_dht_public_key(Net_Crypto *c, int crypt_connection_id, uint8_t return -1; }//TODO + connect_peer_tcp(c, crypt_connection_id); return 0; } @@ -1399,6 +1507,264 @@ int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port) return 0; } +static int tcp_response_callback(void *object, uint8_t connection_id, uint8_t *public_key) +{ + TCP_Client_Connection *TCP_con = object; + Net_Crypto *c = TCP_con->net_crypto_pointer; + + int crypt_connection_id = getcryptconnection_id_dht_pubkey(c, public_key); + + if (crypt_connection_id == -1) + return -1; + + set_tcp_connection_number(TCP_con, connection_id, crypt_connection_id); + + Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); + + if (conn == 0) + return -1; + + uint32_t location = TCP_con->net_crypto_location; + + if (location >= MAX_TCP_CONNECTIONS) + return -1; + + if (c->tcp_connections[location] != TCP_con) + return -1; + + conn->status_tcp[location] = 1; + conn->con_number_tcp[location] = connection_id; + return 0; +} + +static int tcp_status_callback(void *object, uint32_t number, uint8_t connection_id, uint8_t status) +{ + TCP_Client_Connection *TCP_con = object; + Net_Crypto *c = TCP_con->net_crypto_pointer; + + Crypto_Connection *conn = get_crypto_connection(c, number); + + if (conn == 0) + return -1; + + uint32_t location = TCP_con->net_crypto_location; + + if (location >= MAX_TCP_CONNECTIONS) + return -1; + + if (c->tcp_connections[location] != TCP_con) + return -1; + + conn->status_tcp[location] = status; + conn->con_number_tcp[location] = connection_id; + return 0; +} + +static int tcp_data_callback(void *object, uint32_t number, uint8_t connection_id, uint8_t *data, uint16_t length) +{ + if (length == 0) + return -1; + + TCP_Client_Connection *TCP_con = object; + Net_Crypto *c = TCP_con->net_crypto_pointer; + + if (data[0] == NET_PACKET_COOKIE_REQUEST) { + return tcp_handle_cookie_request(c, TCP_con, connection_id, data, length); + } + + Crypto_Connection *conn = get_crypto_connection(c, number); + + if (conn == 0) + return -1; + + if (handle_packet_connection(c, number, data, length) != 0) + return -1; + + //TODO detect and kill bad TCP connections. + return 0; +} + +/* Check if tcp connection to public key can be created. + * + * return -1 if it can't. + * return 0 if it can. + */ +static int tcp_connection_check(Net_Crypto *c, uint8_t *public_key) +{ + uint32_t i; + + for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { + if (c->tcp_connections_new[i] == NULL) + continue; + + if (memcmp(c->tcp_connections_new[i]->public_key, public_key, crypto_box_PUBLICKEYBYTES) == 0) + return -1; + } + + uint32_t num = 0; + + for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { + if (c->tcp_connections[i] == NULL) + continue; + + if (memcmp(c->tcp_connections[i]->public_key, public_key, crypto_box_PUBLICKEYBYTES) == 0) + return -1; + + ++num; + } + + if (num == MAX_TCP_CONNECTIONS) + return -1; + + return 0; +} + +/* Add a tcp relay to the array. + * + * return 0 if it was added. + * return -1 if it wasn't. + */ +int add_tcp_relay(Net_Crypto *c, IP_Port ip_port, uint8_t *public_key) +{ + if (tcp_connection_check(c, public_key) != 0) + return -1; + + uint32_t i; + + for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { + if (c->tcp_connections_new[i] == NULL) { + c->tcp_connections_new[i] = new_TCP_connection(ip_port, public_key, c->dht->self_public_key, c->dht->self_secret_key); + return 0; + } + } + + return -1; +} + +/* Add a connected tcp connection to the tcp_connections array. + * + * return 0 if it was added. + * return -1 if it wasn't. + */ +static int add_tcp_connected(Net_Crypto *c, TCP_Client_Connection *tcp_con) +{ + uint32_t i; + + for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { + if (c->tcp_connections[i] == NULL) + break; + } + + if (i == MAX_TCP_CONNECTIONS) + return -1; + + uint32_t tcp_num = i; + + for (i = 0; i < c->crypto_connections_length; ++i) { + Crypto_Connection *conn = get_crypto_connection(c, i); + + if (conn == 0) + return -1; + + if (conn->status == CRYPTO_CONN_NO_CONNECTION) + continue; + + if (conn->status == CRYPTO_CONN_TIMED_OUT) + continue; + + if (conn->dht_public_key_set) + if (send_routing_request(tcp_con, conn->dht_public_key) != 1) + return -1; + + } + + tcp_con->net_crypto_pointer = c; + tcp_con->net_crypto_location = tcp_num; + routing_response_handler(tcp_con, tcp_response_callback, tcp_con); + routing_status_handler(tcp_con, tcp_status_callback, tcp_con); + routing_data_handler(tcp_con, tcp_data_callback, tcp_con); + c->tcp_connections[tcp_num] = tcp_con; + return 0; +} + +static void do_tcp(Net_Crypto *c) +{ + uint32_t i; + + for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { + if (c->tcp_connections_new[i] == NULL) + continue; + + do_TCP_connection(c->tcp_connections_new[i]); + + if (c->tcp_connections_new[i]->status == TCP_CLIENT_CONFIRMED) { + if (add_tcp_connected(c, c->tcp_connections_new[i]) == 0) { + c->tcp_connections_new[i] = NULL; + } else { + kill_TCP_connection(c->tcp_connections_new[i]); + c->tcp_connections_new[i] = NULL; + } + } + } + + for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { + if (c->tcp_connections[i] == NULL) + continue; + + do_TCP_connection(c->tcp_connections[i]); + } +} + +static void clear_disconnected_tcp_peer(Crypto_Connection *conn, uint32_t number) +{ + if (conn->status == CRYPTO_CONN_NO_CONNECTION) + return; + + if (number >= MAX_TCP_CONNECTIONS) + return; + + conn->status_tcp[number] = 0; + conn->con_number_tcp[number] = 0; +} + +static void clear_disconnected_tcp(Net_Crypto *c) +{ + uint32_t i, j; + + for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { + if (c->tcp_connections_new[i] == NULL) + continue; + + if (c->tcp_connections_new[i]->status != TCP_CLIENT_DISCONNECTED) + continue; + + kill_TCP_connection(c->tcp_connections_new[i]); + c->tcp_connections_new[i] = NULL; + } + + for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { + if (c->tcp_connections[i] == NULL) + continue; + + TCP_Client_Connection *tcp_con = c->tcp_connections[i]; + + if (tcp_con->status != TCP_CLIENT_DISCONNECTED) + continue; + + c->tcp_connections[i] = NULL; + kill_TCP_connection(tcp_con); + + for (j = 0; j < c->crypto_connections_length; ++j) { + Crypto_Connection *conn = get_crypto_connection(c, j); + + if (conn == 0) + return; + + clear_disconnected_tcp_peer(conn, i); + } + } +} + /* Set function to be called when connection with crypt_connection_id goes connects/disconnects. * * The set function should return -1 on failure and 0 on success. @@ -1647,6 +2013,7 @@ int crypto_kill(Net_Crypto *c, int crypt_connection_id) { //TODO send_kill_packet(c, crypt_connection_id); + disconnect_peer_tcp(c, crypt_connection_id); return wipe_crypto_connection(c, crypt_connection_id); } @@ -1764,6 +2131,8 @@ void do_net_crypto(Net_Crypto *c) { unix_time_update(); kill_timedout(c); + do_tcp(c); + clear_disconnected_tcp(c); send_crypto_packets(c); } diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index a010c4d2..22b23401 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -25,6 +25,7 @@ #define NET_CRYPTO_H #include "DHT.h" +#include "TCP_client.h" #define CRYPTO_CONN_NO_CONNECTION 0 #define CRYPTO_CONN_COOKIE_REQUESTING 1 //send cookie request packets @@ -60,6 +61,8 @@ #define CRYPTO_RESERVED_PACKETS 16 +#define MAX_TCP_CONNECTIONS 8 + typedef struct { uint64_t time; uint16_t length; @@ -122,6 +125,9 @@ typedef struct { uint8_t sending; /* indicates if data is being sent or not. */ uint8_t killed; /* set to 1 to kill the connection. */ + + uint8_t status_tcp[MAX_TCP_CONNECTIONS]; + uint8_t con_number_tcp[MAX_TCP_CONNECTIONS]; } Crypto_Connection; typedef struct { @@ -137,7 +143,8 @@ typedef struct { DHT *dht; Crypto_Connection *crypto_connections; - //TCP_Client_Connection *tcp_connections; + TCP_Client_Connection *tcp_connections_new[MAX_TCP_CONNECTIONS]; + TCP_Client_Connection *tcp_connections[MAX_TCP_CONNECTIONS]; uint32_t crypto_connections_length; /* Length of connections array. */ @@ -226,6 +233,12 @@ uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id) */ int64_t write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length); +/* Add a tcp relay to the array. + * + * return 0 if it was added. + * return -1 if it wasn't. + */ +int add_tcp_relay(Net_Crypto *c, IP_Port ip_port, uint8_t *public_key); /* Kill a crypto connection. * From 86c191c2d4d4721f93067565b078b9d691a61c00 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 16 May 2014 17:50:26 -0400 Subject: [PATCH 087/117] Fixed typo. --- toxcore/Messenger.c | 2 +- toxcore/net_crypto.c | 2 +- toxcore/net_crypto.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 267670f9..b5ce2e7e 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -2203,7 +2203,7 @@ void do_friends(Messenger *m) uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; if (onion_getfriend_DHT_pubkey(m->onion_c, m->friendlist[i].onion_friendnum, dht_public_key) == 0) { - set_conection_dht_public_key(m->net_crypto, m->friendlist[i].crypt_connection_id, dht_public_key); + set_connection_dht_public_key(m->net_crypto, m->friendlist[i].crypt_connection_id, dht_public_key); } uint8_t direct_connected; diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 56ff1bdd..6b975fe2 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -1454,7 +1454,7 @@ static int connect_peer_tcp(Net_Crypto *c, int crypt_connection_id) * return -1 on failure. * return 0 on success. */ -int set_conection_dht_public_key(Net_Crypto *c, int crypt_connection_id, uint8_t *dht_public_key) +int set_connection_dht_public_key(Net_Crypto *c, int crypt_connection_id, uint8_t *dht_public_key) { Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index 22b23401..e55427f2 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -189,7 +189,7 @@ int new_crypto_connection(Net_Crypto *c, uint8_t *real_public_key); * return -1 on failure. * return 0 on success. */ -int set_conection_dht_public_key(Net_Crypto *c, int crypt_connection_id, uint8_t *dht_public_key); +int set_connection_dht_public_key(Net_Crypto *c, int crypt_connection_id, uint8_t *dht_public_key); /* Set the direct ip of the crypto connection. * From 454cadb91c57eb689eddbf41d61d66af54aa1e0f Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 17 May 2014 09:21:07 -0400 Subject: [PATCH 088/117] Changed cookie/cookie request packet. Cookie now contains the dht public key of the peer which makes more sense than including the real public key of the reciever. It means we no longer have to rely entirely on onion_client to find the dht public key of the other peer. --- docs/Tox_middle_level_network_protocol.txt | 4 +- toxcore/net_crypto.c | 77 +++++++++++++--------- toxcore/net_crypto.h | 1 + 3 files changed, 48 insertions(+), 34 deletions(-) diff --git a/docs/Tox_middle_level_network_protocol.txt b/docs/Tox_middle_level_network_protocol.txt index 29ea131a..9941487b 100644 --- a/docs/Tox_middle_level_network_protocol.txt +++ b/docs/Tox_middle_level_network_protocol.txt @@ -41,7 +41,7 @@ Detailed implementation details: cookie request packet: [uint8_t 24][Senders DHT Public key (32 bytes)][Random nonce (24 bytes)][Encrypted message containing: [Senders real public key (32 -bytes)][Recievers real public key (32 bytes)][uint64_t number (must be sent +bytes)][padding (32 bytes)][uint64_t number (must be sent back untouched in cookie response)]] Encrypted message is encrypted with sender DHT private key, recievers DHT public key and the nonce. @@ -54,7 +54,7 @@ public key and the nonce. The Cookie should be basically: [nonce][encrypted data:[uint64_t time][Senders real public key (32 -bytes)][Recievers real public key (32 bytes)]] +bytes)][Senders dht public key (32 bytes)]] Handshake packet: [uint8_t 26][Cookie][nonce][Encrypted message containing: [random 24 bytes base diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 6b975fe2..35cf21cd 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -62,20 +62,20 @@ static int is_alive(uint8_t status) /* Create a cookie request packet and put it in packet. * dht_public_key is the dht public key of the other - * real_public_key is the real public key of the other. * * packet must be of size COOKIE_REQUEST_LENGTH or bigger. * * return -1 on failure. * return COOKIE_REQUEST_LENGTH on success. */ -static int create_cookie_request(Net_Crypto *c, uint8_t *packet, uint8_t *dht_public_key, uint8_t *real_public_key, - uint64_t number, uint8_t *shared_key) +static int create_cookie_request(Net_Crypto *c, uint8_t *packet, uint8_t *dht_public_key, uint64_t number, + uint8_t *shared_key) { uint8_t plain[COOKIE_REQUEST_PLAIN_LENGTH]; + uint8_t padding[crypto_box_PUBLICKEYBYTES] = {0}; memcpy(plain, c->self_public_key, crypto_box_PUBLICKEYBYTES); - memcpy(plain + crypto_box_PUBLICKEYBYTES, real_public_key, crypto_box_PUBLICKEYBYTES); + memcpy(plain + crypto_box_PUBLICKEYBYTES, padding, crypto_box_PUBLICKEYBYTES); memcpy(plain + (crypto_box_PUBLICKEYBYTES * 2), &number, sizeof(uint64_t)); DHT_get_shared_key_sent(c->dht, shared_key, dht_public_key); @@ -146,11 +146,15 @@ static int open_cookie(uint8_t *bytes, uint8_t *cookie, uint8_t *encryption_key) * return -1 on failure. * return COOKIE_RESPONSE_LENGTH on success. */ -static int create_cookie_response(Net_Crypto *c, uint8_t *packet, uint8_t *request_plain, uint8_t *shared_key) +static int create_cookie_response(Net_Crypto *c, uint8_t *packet, uint8_t *request_plain, uint8_t *shared_key, + uint8_t *dht_public_key) { + uint8_t cookie_plain[COOKIE_DATA_LENGTH]; + memcpy(cookie_plain, request_plain, crypto_box_PUBLICKEYBYTES); + memcpy(cookie_plain + crypto_box_PUBLICKEYBYTES, dht_public_key, crypto_box_PUBLICKEYBYTES); uint8_t plain[COOKIE_LENGTH + sizeof(uint64_t)]; - if (create_cookie(plain, request_plain, c->secret_symmetric_key) != 0) + if (create_cookie(plain, cookie_plain, c->secret_symmetric_key) != 0) return -1; memcpy(plain + COOKIE_LENGTH, request_plain + COOKIE_DATA_LENGTH, sizeof(uint64_t)); @@ -171,13 +175,14 @@ static int create_cookie_response(Net_Crypto *c, uint8_t *packet, uint8_t *reque * return -1 on failure. * return 0 on success. */ -static int handle_cookie_request(Net_Crypto *c, uint8_t *request_plain, uint8_t *shared_key, uint8_t *packet, - uint16_t length) +static int handle_cookie_request(Net_Crypto *c, uint8_t *request_plain, uint8_t *shared_key, uint8_t *dht_public_key, + uint8_t *packet, uint16_t length) { if (length != COOKIE_REQUEST_LENGTH) return -1; - DHT_get_shared_key_sent(c->dht, shared_key, packet + 1); + memcpy(dht_public_key, packet + 1, crypto_box_PUBLICKEYBYTES); + DHT_get_shared_key_sent(c->dht, shared_key, dht_public_key); int len = decrypt_data_symmetric(shared_key, packet + 1 + crypto_box_PUBLICKEYBYTES, packet + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, COOKIE_REQUEST_PLAIN_LENGTH + crypto_box_MACBYTES, request_plain); @@ -195,13 +200,14 @@ static int udp_handle_cookie_request(void *object, IP_Port source, uint8_t *pack Net_Crypto *c = object; uint8_t request_plain[COOKIE_REQUEST_PLAIN_LENGTH]; uint8_t shared_key[crypto_box_BEFORENMBYTES]; + uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; - if (handle_cookie_request(c, request_plain, shared_key, packet, length) != 0) + if (handle_cookie_request(c, request_plain, shared_key, dht_public_key, packet, length) != 0) return 1; uint8_t data[COOKIE_RESPONSE_LENGTH]; - if (create_cookie_response(c, data, request_plain, shared_key) != sizeof(data)) + if (create_cookie_response(c, data, request_plain, shared_key, dht_public_key) != sizeof(data)) return 1; if ((uint32_t)sendpacket(c->dht->net, source, data, sizeof(data)) != sizeof(data)) @@ -217,13 +223,14 @@ static int tcp_handle_cookie_request(Net_Crypto *c, TCP_Client_Connection *TCP_c { uint8_t request_plain[COOKIE_REQUEST_PLAIN_LENGTH]; uint8_t shared_key[crypto_box_BEFORENMBYTES]; + uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; - if (handle_cookie_request(c, request_plain, shared_key, packet, length) != 0) + if (handle_cookie_request(c, request_plain, shared_key, dht_public_key, packet, length) != 0) return -1; uint8_t data[COOKIE_RESPONSE_LENGTH]; - if (create_cookie_response(c, data, request_plain, shared_key) != sizeof(data)) + if (create_cookie_response(c, data, request_plain, shared_key, dht_public_key) != sizeof(data)) return -1; if ((uint32_t)send_data(TCP_con, conn_id, data, sizeof(data)) != 1) @@ -268,7 +275,7 @@ static int handle_cookie_response(uint8_t *cookie, uint64_t *number, uint8_t *pa * return HANDSHAKE_PACKET_LENGTH on success. */ static int create_crypto_handshake(Net_Crypto *c, uint8_t *packet, uint8_t *cookie, uint8_t *nonce, uint8_t *session_pk, - uint8_t *peer_real_pk) + uint8_t *peer_real_pk, uint8_t *peer_dht_pubkey) { uint8_t plain[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_hash_sha512_BYTES + COOKIE_LENGTH]; memcpy(plain, nonce, crypto_box_NONCEBYTES); @@ -276,7 +283,7 @@ static int create_crypto_handshake(Net_Crypto *c, uint8_t *packet, uint8_t *cook crypto_hash_sha512(plain + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, cookie, COOKIE_LENGTH); uint8_t cookie_plain[COOKIE_DATA_LENGTH]; memcpy(cookie_plain, peer_real_pk, crypto_box_PUBLICKEYBYTES); - memcpy(cookie_plain + crypto_box_PUBLICKEYBYTES, c->self_public_key, crypto_box_PUBLICKEYBYTES); + memcpy(cookie_plain + crypto_box_PUBLICKEYBYTES, peer_dht_pubkey, crypto_box_PUBLICKEYBYTES); if (create_cookie(plain + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_hash_sha512_BYTES, cookie_plain, c->secret_symmetric_key) != 0) @@ -298,7 +305,8 @@ static int create_crypto_handshake(Net_Crypto *c, uint8_t *packet, uint8_t *cook /* Handle a crypto handshake packet of length. * put the nonce contained in the packet in nonce, * the session public key in session_pk - * the real public key of the peer in peer_real_pk and + * the real public key of the peer in peer_real_pk + * the dht public key of the peer in dht_public_key and * the cookie inside the encrypted part of the packet in cookie. * * if expected_real_pk isn't NULL it denotes the real public key @@ -313,7 +321,7 @@ static int create_crypto_handshake(Net_Crypto *c, uint8_t *packet, uint8_t *cook * return 0 on success. */ static int handle_crypto_handshake(Net_Crypto *c, uint8_t *nonce, uint8_t *session_pk, uint8_t *peer_real_pk, - uint8_t *cookie, uint8_t *packet, uint32_t length, uint8_t *expected_real_pk) + uint8_t *dht_public_key, uint8_t *cookie, uint8_t *packet, uint32_t length, uint8_t *expected_real_pk) { if (length != HANDSHAKE_PACKET_LENGTH) return -1; @@ -327,9 +335,6 @@ static int handle_crypto_handshake(Net_Crypto *c, uint8_t *nonce, uint8_t *sessi if (crypto_cmp(cookie_plain, expected_real_pk, crypto_box_PUBLICKEYBYTES) != 0) return -1; - if (crypto_cmp(cookie_plain + crypto_box_PUBLICKEYBYTES, c->self_public_key, crypto_box_PUBLICKEYBYTES) != 0) - return -1; - uint8_t cookie_hash[crypto_hash_sha512_BYTES]; crypto_hash_sha512(cookie_hash, packet + 1, COOKIE_LENGTH); @@ -348,6 +353,7 @@ static int handle_crypto_handshake(Net_Crypto *c, uint8_t *nonce, uint8_t *sessi memcpy(session_pk, plain + crypto_box_NONCEBYTES, crypto_box_PUBLICKEYBYTES); memcpy(cookie, plain + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_hash_sha512_BYTES, COOKIE_LENGTH); memcpy(peer_real_pk, cookie_plain, crypto_box_PUBLICKEYBYTES); + memcpy(dht_public_key, cookie_plain + crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES); return 0; } @@ -933,7 +939,7 @@ static int send_temp_packet(Net_Crypto *c, int crypt_connection_id) * return -1 on failure. * return 0 on success. */ -static int create_send_handshake(Net_Crypto *c, int crypt_connection_id, uint8_t *cookie) +static int create_send_handshake(Net_Crypto *c, int crypt_connection_id, uint8_t *cookie, uint8_t *dht_public_key) { Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); @@ -943,7 +949,7 @@ static int create_send_handshake(Net_Crypto *c, int crypt_connection_id, uint8_t uint8_t handshake_packet[HANDSHAKE_PACKET_LENGTH]; if (create_crypto_handshake(c, handshake_packet, cookie, conn->sent_nonce, conn->sessionpublic_key, - conn->public_key) != sizeof(handshake_packet)) + conn->public_key, dht_public_key) != sizeof(handshake_packet)) return -1; if (new_temp_packet(c, crypt_connection_id, handshake_packet, sizeof(handshake_packet)) != 0) @@ -1083,7 +1089,7 @@ static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, uint if (number != conn->cookie_request_number) return -1; - if (create_send_handshake(c, crypt_connection_id, cookie) != 0) + if (create_send_handshake(c, crypt_connection_id, cookie, conn->dht_public_key) != 0) return -1; conn->status = CRYPTO_CONN_HANDSHAKE_SENT; @@ -1093,20 +1099,23 @@ static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, uint case NET_PACKET_CRYPTO_HS: { if (conn->status == CRYPTO_CONN_COOKIE_REQUESTING || conn->status == CRYPTO_CONN_HANDSHAKE_SENT) { uint8_t peer_real_pk[crypto_box_PUBLICKEYBYTES]; + uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; uint8_t cookie[COOKIE_LENGTH]; - if (handle_crypto_handshake(c, conn->recv_nonce, conn->peersessionpublic_key, peer_real_pk, cookie, packet, length, - conn->public_key) != 0) + if (handle_crypto_handshake(c, conn->recv_nonce, conn->peersessionpublic_key, peer_real_pk, dht_public_key, cookie, + packet, length, conn->public_key) != 0) return -1; encrypt_precompute(conn->peersessionpublic_key, conn->sessionsecret_key, conn->shared_key); if (conn->status == CRYPTO_CONN_COOKIE_REQUESTING) { - if (create_send_handshake(c, crypt_connection_id, cookie) != 0) + if (create_send_handshake(c, crypt_connection_id, cookie, dht_public_key) != 0) return -1; } conn->status = CRYPTO_CONN_NOT_CONFIRMED; + /* Status needs to be CRYPTO_CONN_NOT_CONFIRMED for this to work. */ + set_connection_dht_public_key(c, crypt_connection_id, dht_public_key); } else { return -1; } @@ -1295,8 +1304,8 @@ static int handle_new_connection_handshake(Net_Crypto *c, IP_Port source, uint8_ n_c.source = source; n_c.cookie_length = COOKIE_LENGTH; - if (handle_crypto_handshake(c, n_c.recv_nonce, n_c.peersessionpublic_key, n_c.public_key, n_c.cookie, data, length, - 0) != 0) { + if (handle_crypto_handshake(c, n_c.recv_nonce, n_c.peersessionpublic_key, n_c.public_key, n_c.dht_public_key, + n_c.cookie, data, length, 0) != 0) { free(n_c.cookie); return -1; } @@ -1314,8 +1323,10 @@ static int handle_new_connection_handshake(Net_Crypto *c, IP_Port source, uint8_ crypto_connection_add_source(c, crypt_connection_id, source); - if (create_send_handshake(c, crypt_connection_id, n_c.cookie) == 0) { + if (create_send_handshake(c, crypt_connection_id, n_c.cookie, n_c.dht_public_key) == 0) { conn->status = CRYPTO_CONN_NOT_CONFIRMED; + /* Status needs to be CRYPTO_CONN_NOT_CONFIRMED for this to work. */ + set_connection_dht_public_key(c, crypt_connection_id, n_c.dht_public_key); ret = 0; } } @@ -1359,10 +1370,12 @@ int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c) if (n_c->cookie_length != COOKIE_LENGTH) return -1; - if (create_send_handshake(c, crypt_connection_id, n_c->cookie) != 0) + if (create_send_handshake(c, crypt_connection_id, n_c->cookie, n_c->dht_public_key) != 0) return -1; conn->status = CRYPTO_CONN_NOT_CONFIRMED; + /* Status needs to be CRYPTO_CONN_NOT_CONFIRMED for this to work. */ + set_connection_dht_public_key(c, crypt_connection_id, n_c->dht_public_key); conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE; crypto_connection_add_source(c, crypt_connection_id, n_c->source); return crypt_connection_id; @@ -1475,8 +1488,8 @@ int set_connection_dht_public_key(Net_Crypto *c, int crypt_connection_id, uint8_ conn->cookie_request_number = random_64b(); uint8_t cookie_request[COOKIE_REQUEST_LENGTH]; - if (create_cookie_request(c, cookie_request, conn->dht_public_key, conn->public_key, - conn->cookie_request_number, conn->shared_key) != sizeof(cookie_request)) + if (create_cookie_request(c, cookie_request, conn->dht_public_key, conn->cookie_request_number, + conn->shared_key) != sizeof(cookie_request)) return -1; if (new_temp_packet(c, crypt_connection_id, cookie_request, sizeof(cookie_request)) != 0) diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index e55427f2..e2e0fffb 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -133,6 +133,7 @@ typedef struct { typedef struct { IP_Port source; uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* The real public key of the peer. */ + uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; /* The dht public key of the peer. */ uint8_t recv_nonce[crypto_box_NONCEBYTES]; /* Nonce of received packets. */ uint8_t peersessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* The public key of the peer. */ uint8_t *cookie; From a5da6df1442f0615e727292ab58f90f169e090cf Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 17 May 2014 12:33:22 -0400 Subject: [PATCH 089/117] Net_crypto can now handle packets sent as TCP OOB packets. Added timestamp to know which DHT public key is good in case onion_client and net_crypto report different ones. --- toxcore/Messenger.c | 5 +-- toxcore/net_crypto.c | 80 +++++++++++++++++++++++++++++++++++++++--- toxcore/net_crypto.h | 5 ++- toxcore/network.h | 1 + toxcore/onion_client.c | 17 ++++----- toxcore/onion_client.h | 7 ++-- toxcore/tox.c | 2 +- 7 files changed, 97 insertions(+), 20 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index b5ce2e7e..2c7dcdee 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -2202,8 +2202,9 @@ void do_friends(Messenger *m) friend_new_connection(m, i, m->friendlist[i].client_id); uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; - if (onion_getfriend_DHT_pubkey(m->onion_c, m->friendlist[i].onion_friendnum, dht_public_key) == 0) { - set_connection_dht_public_key(m->net_crypto, m->friendlist[i].crypt_connection_id, dht_public_key); + uint64_t timestamp = onion_getfriend_DHT_pubkey(m->onion_c, m->friendlist[i].onion_friendnum, dht_public_key); + if (timestamp != 0) { + set_connection_dht_public_key(m->net_crypto, m->friendlist[i].crypt_connection_id, dht_public_key, timestamp); } uint8_t direct_connected; diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 35cf21cd..2f01bc83 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -233,7 +233,33 @@ static int tcp_handle_cookie_request(Net_Crypto *c, TCP_Client_Connection *TCP_c if (create_cookie_response(c, data, request_plain, shared_key, dht_public_key) != sizeof(data)) return -1; - if ((uint32_t)send_data(TCP_con, conn_id, data, sizeof(data)) != 1) + if (send_data(TCP_con, conn_id, data, sizeof(data)) != 1) + return -1; + + return 0; +} + +/* Handle the cookie request packet (for TCP oob packets) + */ +static int tcp_oob_handle_cookie_request(Net_Crypto *c, TCP_Client_Connection *TCP_con, uint8_t *dht_public_key, + uint8_t *packet, uint32_t length) +{ + uint8_t request_plain[COOKIE_REQUEST_PLAIN_LENGTH]; + uint8_t shared_key[crypto_box_BEFORENMBYTES]; + uint8_t dht_public_key_temp[crypto_box_PUBLICKEYBYTES]; + + if (handle_cookie_request(c, request_plain, shared_key, dht_public_key_temp, packet, length) != 0) + return -1; + + if (memcmp(dht_public_key, dht_public_key_temp, crypto_box_PUBLICKEYBYTES) != 0) + return -1; + + uint8_t data[COOKIE_RESPONSE_LENGTH]; + + if (create_cookie_response(c, data, request_plain, shared_key, dht_public_key) != sizeof(data)) + return -1; + + if (send_oob_packet(TCP_con, dht_public_key, data, sizeof(data)) != 1) return -1; return 0; @@ -1115,7 +1141,7 @@ static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, uint conn->status = CRYPTO_CONN_NOT_CONFIRMED; /* Status needs to be CRYPTO_CONN_NOT_CONFIRMED for this to work. */ - set_connection_dht_public_key(c, crypt_connection_id, dht_public_key); + set_connection_dht_public_key(c, crypt_connection_id, dht_public_key, current_time_monotonic()); } else { return -1; } @@ -1326,7 +1352,7 @@ static int handle_new_connection_handshake(Net_Crypto *c, IP_Port source, uint8_ if (create_send_handshake(c, crypt_connection_id, n_c.cookie, n_c.dht_public_key) == 0) { conn->status = CRYPTO_CONN_NOT_CONFIRMED; /* Status needs to be CRYPTO_CONN_NOT_CONFIRMED for this to work. */ - set_connection_dht_public_key(c, crypt_connection_id, n_c.dht_public_key); + set_connection_dht_public_key(c, crypt_connection_id, n_c.dht_public_key, current_time_monotonic()); ret = 0; } } @@ -1375,7 +1401,7 @@ int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c) conn->status = CRYPTO_CONN_NOT_CONFIRMED; /* Status needs to be CRYPTO_CONN_NOT_CONFIRMED for this to work. */ - set_connection_dht_public_key(c, crypt_connection_id, n_c->dht_public_key); + set_connection_dht_public_key(c, crypt_connection_id, n_c->dht_public_key, current_time_monotonic()); conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE; crypto_connection_add_source(c, crypt_connection_id, n_c->source); return crypt_connection_id; @@ -1463,17 +1489,22 @@ static int connect_peer_tcp(Net_Crypto *c, int crypt_connection_id) } /* Set the DHT public key of the crypto connection. + * timestamp is the time (current_time_monotonic()) at which the key was last confirmed belonging to + * the other peer. * * return -1 on failure. * return 0 on success. */ -int set_connection_dht_public_key(Net_Crypto *c, int crypt_connection_id, uint8_t *dht_public_key) +int set_connection_dht_public_key(Net_Crypto *c, int crypt_connection_id, uint8_t *dht_public_key, uint64_t timestamp) { Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); if (conn == 0) return -1; + if (timestamp <= conn->dht_public_key_timestamp) + return -1; + if (conn->dht_public_key_set == 1 && memcmp(conn->dht_public_key, dht_public_key, crypto_box_PUBLICKEYBYTES) == 0) return -1; @@ -1483,6 +1514,7 @@ int set_connection_dht_public_key(Net_Crypto *c, int crypt_connection_id, uint8_ memcpy(conn->dht_public_key, dht_public_key, crypto_box_PUBLICKEYBYTES); conn->dht_public_key_set = 1; + conn->dht_public_key_timestamp = timestamp; if (conn->status == CRYPTO_CONN_COOKIE_REQUESTING) { conn->cookie_request_number = random_64b(); @@ -1597,6 +1629,43 @@ static int tcp_data_callback(void *object, uint32_t number, uint8_t connection_i return 0; } +static int tcp_oob_callback(void *object, uint8_t *public_key, uint8_t *data, uint16_t length) +{ + if (length == 0 || length > MAX_CRYPTO_PACKET_SIZE) + return -1; + + TCP_Client_Connection *TCP_con = object; + Net_Crypto *c = TCP_con->net_crypto_pointer; + uint32_t location = TCP_con->net_crypto_location; + + if (data[0] == NET_PACKET_COOKIE_REQUEST) { + return tcp_oob_handle_cookie_request(c, TCP_con, public_key, data, length); + } + + int crypt_connection_id = getcryptconnection_id_dht_pubkey(c, public_key); + + if (crypt_connection_id == -1) { + IP_Port source; + source.ip.family = TCP_FAMILY; + source.ip.ip6.uint32[0] = location; + + if (data[0] != NET_PACKET_CRYPTO_HS) { + fprintf(stderr, "tcp snhappen %u\n", data[0]); + return -1; + } + + if (handle_new_connection_handshake(c, source, data, length) != 0) + return -1; + + return 0; + } + + if (handle_packet_connection(c, crypt_connection_id, data, length) != 0) + return -1; + + return 0; +} + /* Check if tcp connection to public key can be created. * * return -1 if it can't. @@ -1696,6 +1765,7 @@ static int add_tcp_connected(Net_Crypto *c, TCP_Client_Connection *tcp_con) routing_response_handler(tcp_con, tcp_response_callback, tcp_con); routing_status_handler(tcp_con, tcp_status_callback, tcp_con); routing_data_handler(tcp_con, tcp_data_callback, tcp_con); + oob_data_handler(tcp_con, tcp_oob_callback, tcp_con); c->tcp_connections[tcp_num] = tcp_con; return 0; } diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index e2e0fffb..dbbb295c 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -92,6 +92,7 @@ typedef struct { uint64_t cookie_request_number; /* number used in the cookie request packets for this connection */ uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; /* The dht public key of the peer */ uint8_t dht_public_key_set; /* True if the dht public key is set, false if it isn't. */ + uint64_t dht_public_key_timestamp; /* Timestamp of the last time we confirmed the key was correct. */ uint8_t *temp_packet; /* Where the cookie request/handshake packet is stored while it is being sent. */ uint16_t temp_packet_length; @@ -186,11 +187,13 @@ int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c); int new_crypto_connection(Net_Crypto *c, uint8_t *real_public_key); /* Set the DHT public key of the crypto connection. + * timestamp is the time (current_time_monotonic()) at which the key was last confirmed belonging to + * the other peer. * * return -1 on failure. * return 0 on success. */ -int set_connection_dht_public_key(Net_Crypto *c, int crypt_connection_id, uint8_t *dht_public_key); +int set_connection_dht_public_key(Net_Crypto *c, int crypt_connection_id, uint8_t *dht_public_key, uint64_t timestamp); /* Set the direct ip of the crypto connection. * diff --git a/toxcore/network.h b/toxcore/network.h index e268df74..f907b9b5 100644 --- a/toxcore/network.h +++ b/toxcore/network.h @@ -154,6 +154,7 @@ typedef int sock_t; #define TCP_ONION_FAMILY (AF_INET6 + 1) #define TCP_INET (AF_INET6 + 2) #define TCP_INET6 (AF_INET6 + 3) +#define TCP_FAMILY (AF_INET6 + 4) typedef union __attribute__ ((__packed__)) { diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index 73cb1f75..16333e0c 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c @@ -509,6 +509,7 @@ static int handle_fakeid_announce(void *object, uint8_t *source_pubkey, uint8_t } onion_c->friends_list[friend_num].is_fake_clientid = 1; + onion_c->friends_list[friend_num].fake_client_id_timestamp = current_time_monotonic(); memcpy(onion_c->friends_list[friend_num].fake_client_id, data + 1 + sizeof(uint64_t), crypto_box_PUBLICKEYBYTES); } @@ -814,22 +815,22 @@ int onion_delfriend(Onion_Client *onion_c, int friend_num) /* Copy friends DHT public key into dht_key. * - * return -1 on failure (no key copied). - * return 0 on success (key copied). + * return 0 on failure (no key copied). + * return timestamp on success (key copied). */ -int onion_getfriend_DHT_pubkey(Onion_Client *onion_c, int friend_num, uint8_t *dht_key) +uint64_t onion_getfriend_DHT_pubkey(Onion_Client *onion_c, int friend_num, uint8_t *dht_key) { if ((uint32_t)friend_num >= onion_c->num_friends) - return -1; + return 0; if (onion_c->friends_list[friend_num].status == 0) - return -1; + return 0; if (!onion_c->friends_list[friend_num].is_fake_clientid) - return -1; + return 0; memcpy(dht_key, onion_c->friends_list[friend_num].fake_client_id, crypto_box_PUBLICKEYBYTES); - return 0; + return onion_c->friends_list[friend_num].fake_client_id_timestamp; } /* Get the ip of friend friendnum and put it in ip_port @@ -843,7 +844,7 @@ int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port) { uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; - if (onion_getfriend_DHT_pubkey(onion_c, friend_num, dht_public_key) != 0) + if (onion_getfriend_DHT_pubkey(onion_c, friend_num, dht_public_key) == 0) return -1; return DHT_getfriendip(onion_c->dht, dht_public_key, ip_port); diff --git a/toxcore/onion_client.h b/toxcore/onion_client.h index 06909380..1d56333a 100644 --- a/toxcore/onion_client.h +++ b/toxcore/onion_client.h @@ -82,6 +82,7 @@ typedef struct { 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. */ + uint64_t fake_client_id_timestamp; uint8_t fake_client_id[crypto_box_PUBLICKEYBYTES]; uint8_t real_client_id[crypto_box_PUBLICKEYBYTES]; @@ -177,10 +178,10 @@ int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port); /* Copy friends DHT public key into dht_key. * - * return -1 on failure (no key copied). - * return 0 on success (key copied). + * return 0 on failure (no key copied). + * return timestamp on success (key copied). */ -int onion_getfriend_DHT_pubkey(Onion_Client *onion_c, int friend_num, uint8_t *dht_key); +uint64_t onion_getfriend_DHT_pubkey(Onion_Client *onion_c, int friend_num, uint8_t *dht_key); #define ONION_DATA_IN_RESPONSE_MIN_SIZE (crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES) #define ONION_CLIENT_MAX_DATA_SIZE (MAX_DATA_REQUEST_SIZE - ONION_DATA_IN_RESPONSE_MIN_SIZE) diff --git a/toxcore/tox.c b/toxcore/tox.c index d49e2241..d86f1a17 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -721,7 +721,7 @@ int tox_file_send_data(Tox *tox, int32_t friendnumber, uint8_t filenumber, uint8 */ int tox_file_data_size(Tox *tox, int32_t friendnumber) { - return MAX_CRYPTO_DATA_SIZE - 3; + return MAX_CRYPTO_DATA_SIZE - 2; } /* Give the number of bytes left to be sent/received. From 3aef4711ce4587fe3e48e505eff61373100fd335 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 17 May 2014 13:16:58 -0400 Subject: [PATCH 090/117] Added function to set the DHT public key in onion_client. --- toxcore/onion_client.c | 54 ++++++++++++++++++++++++++++++------------ toxcore/onion_client.h | 9 +++++++ 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index 16333e0c..be4d12aa 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c @@ -497,21 +497,8 @@ static int handle_fakeid_announce(void *object, uint8_t *source_pubkey, uint8_t 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); - - onion_c->friends_list[friend_num].last_seen = unix_time(); - - if (DHT_addfriend(onion_c->dht, data + 1 + sizeof(uint64_t)) == 1) { - return 1; - } - - onion_c->friends_list[friend_num].is_fake_clientid = 1; - onion_c->friends_list[friend_num].fake_client_id_timestamp = current_time_monotonic(); - memcpy(onion_c->friends_list[friend_num].fake_client_id, data + 1 + sizeof(uint64_t), crypto_box_PUBLICKEYBYTES); - } + onion_set_friend_DHT_pubkey(onion_c, friend_num, data + 1 + sizeof(uint64_t), current_time_monotonic()); + onion_c->friends_list[friend_num].last_seen = unix_time(); uint16_t len_nodes = length - FAKEID_DATA_MIN_LENGTH; @@ -813,6 +800,43 @@ int onion_delfriend(Onion_Client *onion_c, int friend_num) return friend_num; } +/* Set a friends DHT public key. + * timestamp is the time (current_time_monotonic()) at which the key was last confirmed belonging to + * the other peer. + * + * return -1 on failure. + * return 0 on success. + */ +int onion_set_friend_DHT_pubkey(Onion_Client *onion_c, int friend_num, uint8_t *dht_key, uint64_t timestamp) +{ + if ((uint32_t)friend_num >= onion_c->num_friends) + return -1; + + if (onion_c->friends_list[friend_num].status == 0) + return -1; + + if (onion_c->friends_list[friend_num].fake_client_id_timestamp >= timestamp) + return -1; + + if (onion_c->friends_list[friend_num].is_fake_clientid) { + if (memcmp(dht_key, onion_c->friends_list[friend_num].fake_client_id, crypto_box_PUBLICKEYBYTES) == 0) { + return -1; + } + + DHT_delfriend(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id); + } + + if (DHT_addfriend(onion_c->dht, dht_key) == 1) { + return -1; + } + + onion_c->friends_list[friend_num].is_fake_clientid = 1; + onion_c->friends_list[friend_num].fake_client_id_timestamp = timestamp; + memcpy(onion_c->friends_list[friend_num].fake_client_id, dht_key, crypto_box_PUBLICKEYBYTES); + + return 0; +} + /* Copy friends DHT public key into dht_key. * * return 0 on failure (no key copied). diff --git a/toxcore/onion_client.h b/toxcore/onion_client.h index 1d56333a..029f5624 100644 --- a/toxcore/onion_client.h +++ b/toxcore/onion_client.h @@ -176,6 +176,15 @@ int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_on */ int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port); +/* Set a friends DHT public key. + * timestamp is the time (current_time_monotonic()) at which the key was last confirmed belonging to + * the other peer. + * + * return -1 on failure. + * return 0 on success. + */ +int onion_set_friend_DHT_pubkey(Onion_Client *onion_c, int friend_num, uint8_t *dht_key, uint64_t timestamp); + /* Copy friends DHT public key into dht_key. * * return 0 on failure (no key copied). From 80e4e5663fac23c4f57f58264caff6aa04a27713 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 17 May 2014 14:29:28 -0400 Subject: [PATCH 091/117] Fixed bug in TCP server where memory was expected to be zero but sometimes wasn't. --- toxcore/TCP_server.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/toxcore/TCP_server.c b/toxcore/TCP_server.c index 31884604..ceab5f10 100644 --- a/toxcore/TCP_server.c +++ b/toxcore/TCP_server.c @@ -73,12 +73,22 @@ static int realloc_connection(TCP_Server *TCP_server, uint32_t num) return 0; } + if (num == TCP_server->size_accepted_connections) { + return 0; + } + TCP_Secure_Connection *new_connections = realloc(TCP_server->accepted_connection_array, num * sizeof(TCP_Secure_Connection)); if (new_connections == NULL) return -1; + if (num > TCP_server->size_accepted_connections) { + uint32_t old_size = TCP_server->size_accepted_connections; + uint32_t size_new_entries = (num - old_size) * sizeof(TCP_Secure_Connection); + memset(new_connections + old_size, 0, size_new_entries); + } + TCP_server->accepted_connection_array = new_connections; TCP_server->size_accepted_connections = num; return 0; From 60ed415a5a36ac253a343f403e1bbfb620ae571a Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 17 May 2014 14:56:20 -0400 Subject: [PATCH 092/117] Added a function to get the DHT public key stored in net_crypto. The DHT public keys in onion_client/net_crypto are synced and set to whichever is more recent. Tox peers now try to connect directly even when already connected with a TCP relay. --- toxcore/Messenger.c | 11 ++++++++++- toxcore/net_crypto.c | 30 +++++++++++++++++++++++++++++- toxcore/net_crypto.h | 7 +++++++ 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 2c7dcdee..b0d5a2e5 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -2200,13 +2200,22 @@ void do_friends(Messenger *m) } friend_new_connection(m, i, m->friendlist[i].client_id); - uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; + } + if (m->friendlist[i].crypt_connection_id != -1) { + uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; uint64_t timestamp = onion_getfriend_DHT_pubkey(m->onion_c, m->friendlist[i].onion_friendnum, dht_public_key); + if (timestamp != 0) { set_connection_dht_public_key(m->net_crypto, m->friendlist[i].crypt_connection_id, dht_public_key, timestamp); } + timestamp = get_connection_dht_key(m->net_crypto, m->friendlist[i].crypt_connection_id, dht_public_key); + + if (timestamp != 0) { + onion_set_friend_DHT_pubkey(m->onion_c, m->friendlist[i].onion_friendnum, dht_public_key, timestamp); + } + uint8_t direct_connected; unsigned int status = crypto_connection_status(m->net_crypto, m->friendlist[i].crypt_connection_id, &direct_connected); diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 2f01bc83..8230a41d 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -408,8 +408,16 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, uint8_t *data, //TODO: on bad networks, direct connections might not last indefinitely. if (conn->ip_port.ip.family != 0) { - if ((uint32_t)sendpacket(c->dht->net, conn->ip_port, data, length) == length) + uint8_t direct_connected = 0; + crypto_connection_status(c, crypt_connection_id, &direct_connected); + + if (direct_connected && (uint32_t)sendpacket(c->dht->net, conn->ip_port, data, length) == length) return 0; + + if (length < 96 + || data[0] == NET_PACKET_CRYPTO_HS) //TODO: a better way of sending packets directly to confirm the others ip. + sendpacket(c->dht->net, conn->ip_port, data, length); + } //TODO: spread packets over many relays, detect and kill bad relays. @@ -1488,6 +1496,26 @@ static int connect_peer_tcp(Net_Crypto *c, int crypt_connection_id) return 0; } +/* Copy friends DHT public key into dht_key. + * + * return 0 on failure (no key copied). + * return timestamp on success (key copied). + */ +uint64_t get_connection_dht_key(Net_Crypto *c, int crypt_connection_id, uint8_t *dht_public_key) +{ + Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); + + if (conn == 0) + return 0; + + if (conn->dht_public_key_set == 0) + return 0; + + memcpy(dht_public_key, conn->dht_public_key, crypto_box_PUBLICKEYBYTES); + return conn->dht_public_key_timestamp; +} + + /* Set the DHT public key of the crypto connection. * timestamp is the time (current_time_monotonic()) at which the key was last confirmed belonging to * the other peer. diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index dbbb295c..e41e7e1d 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -186,6 +186,13 @@ int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c); */ int new_crypto_connection(Net_Crypto *c, uint8_t *real_public_key); +/* Copy friends DHT public key into dht_key. + * + * return 0 on failure (no key copied). + * return timestamp on success (key copied). + */ +uint64_t get_connection_dht_key(Net_Crypto *c, int crypt_connection_id, uint8_t *dht_public_key); + /* Set the DHT public key of the crypto connection. * timestamp is the time (current_time_monotonic()) at which the key was last confirmed belonging to * the other peer. From b5f84b33f707484890357215593eeb8b1e77bdda Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 17 May 2014 15:23:16 -0400 Subject: [PATCH 093/117] net_crypto now works again on pure UDP. --- toxcore/net_crypto.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 8230a41d..1e3456c3 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -414,8 +414,8 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, uint8_t *data, if (direct_connected && (uint32_t)sendpacket(c->dht->net, conn->ip_port, data, length) == length) return 0; - if (length < 96 - || data[0] == NET_PACKET_CRYPTO_HS) //TODO: a better way of sending packets directly to confirm the others ip. + //TODO: a better way of sending packets directly to confirm the others ip. + if (length < 96 || data[0] == NET_PACKET_COOKIE_REQUEST || data[0] == NET_PACKET_CRYPTO_HS) sendpacket(c->dht->net, conn->ip_port, data, length); } From ceaeae8cffad13403618c2b4ffaf90d854e36cbe Mon Sep 17 00:00:00 2001 From: Maxim Biro Date: Sat, 17 May 2014 20:36:16 -0400 Subject: [PATCH 094/117] Added TCP server functionality --- other/bootstrap_daemon/conf | 6 + other/bootstrap_daemon/tox_bootstrap_daemon.c | 143 +++++++++++++++++- 2 files changed, 141 insertions(+), 8 deletions(-) diff --git a/other/bootstrap_daemon/conf b/other/bootstrap_daemon/conf index 28e638c1..fb524754 100644 --- a/other/bootstrap_daemon/conf +++ b/other/bootstrap_daemon/conf @@ -20,6 +20,12 @@ enable_ipv6 = false // Automatically bootstrap with nodes on local area network. enable_lan_discovery = true +enable_tcp_relay = true + +// Tox uses 443 and 3389 ports by default, so it's highly recommended to keep +// them +tcp_relay_ports = [443, 3389] + // Any number of nodes the daemon will bootstrap itself from. // Remember to replace the provided example with your own node list. // There is a maintained list of bootstrap nodes on Tox's wiki, if you need it. diff --git a/other/bootstrap_daemon/tox_bootstrap_daemon.c b/other/bootstrap_daemon/tox_bootstrap_daemon.c index abad7760..8d3ed94a 100644 --- a/other/bootstrap_daemon/tox_bootstrap_daemon.c +++ b/other/bootstrap_daemon/tox_bootstrap_daemon.c @@ -21,25 +21,33 @@ * */ -#include -#include -#include +// system provided +#include #include +#include +#include +#include +// C #include #include -#include -#include #include +// 3rd party +#include + +// ./configure #ifdef HAVE_CONFIG_H #include "config.h" #endif -#include "../../toxcore/onion_announce.h" +// toxcore #include "../../toxcore/LAN_discovery.h" +#include "../../toxcore/onion_announce.h" +#include "../../toxcore/TCP_server.h" #include "../../toxcore/util.h" +// misc #include "../../testing/misc_tools.c" #define DAEMON_NAME "tox_bootstrap_daemon" @@ -52,6 +60,7 @@ #define DEFAULT_PORT 33445 #define DEFAULT_ENABLE_IPV6 0 // 1 - true, 0 - false #define DEFAULT_ENABLE_LAN_DISCOVERY 1 // 1 - true, 0 - false +#define DEFAULT_ENABLE_TCP_RELAY 1 // Uses the already existing key or creates one if it didn't exist @@ -96,15 +105,79 @@ int manage_keys(DHT *dht, char *keys_file_path) return 1; } +// Parses tcp relay ports from `cfg` and puts them into `tcp_relay_ports` array +// +// Supposed to be called from get_general_config only +// +// Important: iff `tcp_relay_port_count` > 0, then you are responsible for freeing `tcp_relay_ports` + +void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_ports, int *tcp_relay_port_count) +{ + const char *NAME_TCP_RELAY_PORTS = "tcp_relay_ports"; + + *tcp_relay_port_count = 0; + + config_setting_t *ports_array = config_lookup(cfg, NAME_TCP_RELAY_PORTS); + + if (ports_array == NULL) { + syslog(LOG_WARNING, "No '%s' setting in the configuration file.\n", NAME_TCP_RELAY_PORTS); + return; + } + + if (config_setting_is_array(ports_array) == CONFIG_FALSE) { + syslog(LOG_WARNING, "'%s' setting should be an array. Array syntax: 'setting = [value1, value2, ...]'.\n"); + return; + } + + int config_port_count = config_setting_length(ports_array); + if (config_port_count == 0) { + syslog(LOG_WARNING, "'%s' is empty.\n", NAME_TCP_RELAY_PORTS); + return; + } + + *tcp_relay_ports = malloc(config_port_count * sizeof(uint16_t)); + + config_setting_t *elem; + int i; + + for (i = 0; i < config_port_count; i ++) { + + elem = config_setting_get_elem(ports_array, i); + + if (elem == NULL) { + // it's NULL if `ports_array` is not an array (we have that check ealier) or if `i` is out of range, which should not be + syslog(LOG_WARNING, "Port #%d: Something went wrong while parsing the port. Stopping reading ports.\n", i); + break; + } + + if (config_setting_is_number(elem) == CONFIG_FALSE) { + syslog(LOG_WARNING, "Port #%d: Not a number. Skipping.\n", i); + continue; + } + + (*tcp_relay_ports)[*tcp_relay_port_count] = config_setting_get_int(elem); + if ((*tcp_relay_ports)[i] < 1 || (*tcp_relay_ports)[i] > 65535) { + syslog(LOG_WARNING, "Port #%d: Invalid port value, should be in [1, 65535]. Skipping.\n", i); + continue; + } + + (*tcp_relay_port_count) ++; + } + + // the loop above skips invalid ports, so we adjust the allocated memory size + *tcp_relay_ports = realloc(*tcp_relay_ports, *tcp_relay_port_count * sizeof(uint16_t)); +} + // Gets general config options // // Important: you are responsible for freeing `pid_file_path` and `keys_file_path` +// also, iff `tcp_relay_ports_count` > 0, then you are responsible for freeing `tcp_relay_ports` // // returns 1 on success // 0 on failure, doesn't modify any data pointed by arguments int get_general_config(char *cfg_file_path, char **pid_file_path, char **keys_file_path, int *port, int *enable_ipv6, - int *enable_lan_discovery) + int *enable_lan_discovery, int *enable_tcp_relay, uint16_t **tcp_relay_ports, int *tcp_relay_port_count) { config_t cfg; @@ -113,6 +186,7 @@ int get_general_config(char *cfg_file_path, char **pid_file_path, char **keys_fi const char *NAME_KEYS_FILE_PATH = "keys_file_path"; const char *NAME_ENABLE_IPV6 = "enable_ipv6"; const char *NAME_ENABLE_LAN_DISCOVERY = "enable_lan_discovery"; + const char *NAME_ENABLE_TCP_RELAY = "enable_tcp_relay"; config_init(&cfg); @@ -169,6 +243,20 @@ int get_general_config(char *cfg_file_path, char **pid_file_path, char **keys_fi *enable_lan_discovery = DEFAULT_ENABLE_LAN_DISCOVERY; } + // Get TCP relay option + if (config_lookup_bool(&cfg, NAME_ENABLE_TCP_RELAY, enable_tcp_relay) == CONFIG_FALSE) { + syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_TCP_RELAY); + syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_ENABLE_TCP_RELAY, + DEFAULT_ENABLE_TCP_RELAY ? "true" : "false"); + *enable_tcp_relay = DEFAULT_ENABLE_TCP_RELAY; + } + + if (*enable_tcp_relay) { + parse_tcp_relay_ports_config(&cfg, tcp_relay_ports, tcp_relay_port_count); + } else { + *tcp_relay_port_count = 0; + } + config_destroy(&cfg); syslog(LOG_DEBUG, "Successfully read:\n"); @@ -177,6 +265,19 @@ int get_general_config(char *cfg_file_path, char **pid_file_path, char **keys_fi syslog(LOG_DEBUG, "'%s': %d\n", NAME_PORT, *port); syslog(LOG_DEBUG, "'%s': %s\n", NAME_ENABLE_IPV6, *enable_ipv6 ? "true" : "false"); syslog(LOG_DEBUG, "'%s': %s\n", NAME_ENABLE_LAN_DISCOVERY, *enable_lan_discovery ? "true" : "false"); + syslog(LOG_DEBUG, "'%s': %s\n", NAME_ENABLE_TCP_RELAY, *enable_tcp_relay ? "true" : "false"); + // show info about tcp ports only if tcp relay is enabled + if (*enable_tcp_relay) { + if (*tcp_relay_port_count == 0) { + syslog(LOG_DEBUG, "No TCP ports could be read.\n"); + } else { + syslog(LOG_DEBUG, "Read %d TCP ports:\n", *tcp_relay_port_count); + int i; + for (i = 0; i < *tcp_relay_port_count; i ++) { + syslog(LOG_DEBUG, "Port #%d: %u\n", i, (*tcp_relay_ports)[i]); + } + } + } return 1; } @@ -325,8 +426,11 @@ int main(int argc, char *argv[]) int port; int enable_ipv6; int enable_lan_discovery; + int enable_tcp_relay; + uint16_t *tcp_relay_ports; + int tcp_relay_port_count; - if (get_general_config(cfg_file_path, &pid_file_path, &keys_file_path, &port, &enable_ipv6, &enable_lan_discovery)) { + if (get_general_config(cfg_file_path, &pid_file_path, &keys_file_path, &port, &enable_ipv6, &enable_lan_discovery, &enable_tcp_relay, &tcp_relay_ports, &tcp_relay_port_count)) { syslog(LOG_DEBUG, "General config read successfully\n"); } else { syslog(LOG_ERR, "Couldn't read config file: %s. Exiting.\n", cfg_file_path); @@ -374,6 +478,25 @@ int main(int argc, char *argv[]) return 1; } + TCP_Server *tcp_server = NULL; + + if (enable_tcp_relay) { + if (tcp_relay_port_count == 0) { + syslog(LOG_ERR, "No TCP relay ports read. Exiting.\n"); + return 1; + } + + tcp_server = new_TCP_server(enable_ipv6, tcp_relay_port_count, tcp_relay_ports, dht->self_public_key, dht->self_secret_key, onion); + + // tcp_relay_port_count != 0 at this point + free(tcp_relay_ports); + + if (tcp_server == NULL) { + syslog(LOG_ERR, "Couldn't initialize Tox TCP server. Exiting.\n"); + return 1; + } + } + if (bootstrap_from_config(cfg_file_path, dht, enable_ipv6)) { syslog(LOG_DEBUG, "List of bootstrap nodes read successfully\n"); } else { @@ -443,6 +566,10 @@ int main(int argc, char *argv[]) last_LANdiscovery = unix_time(); } + if (enable_tcp_relay) { + do_TCP_server(tcp_server); + } + networking_poll(dht->net); if (waiting_for_dht_connection && DHT_isconnected(dht)) { From 9d4947ffa5bb176628528887f46bcd0b405a9edd Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 17 May 2014 21:30:52 -0400 Subject: [PATCH 095/117] add_tcp_relay_peer() can be used to add relays that we know that peer is connected to. Some cleanups/fixes. --- toxcore/Messenger.c | 18 ++++----- toxcore/TCP_client.c | 3 ++ toxcore/net_crypto.c | 91 ++++++++++++++++++++++++++++++++++++++---- toxcore/net_crypto.h | 20 +++++++++- toxcore/onion_client.c | 1 + 5 files changed, 114 insertions(+), 19 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index b0d5a2e5..472c2ae4 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -2203,17 +2203,15 @@ void do_friends(Messenger *m) } if (m->friendlist[i].crypt_connection_id != -1) { - uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; - uint64_t timestamp = onion_getfriend_DHT_pubkey(m->onion_c, m->friendlist[i].onion_friendnum, dht_public_key); + uint8_t dht_public_key1[crypto_box_PUBLICKEYBYTES]; + uint64_t timestamp1 = onion_getfriend_DHT_pubkey(m->onion_c, m->friendlist[i].onion_friendnum, dht_public_key1); + uint8_t dht_public_key2[crypto_box_PUBLICKEYBYTES]; + uint64_t timestamp2 = get_connection_dht_key(m->net_crypto, m->friendlist[i].crypt_connection_id, dht_public_key2); - if (timestamp != 0) { - set_connection_dht_public_key(m->net_crypto, m->friendlist[i].crypt_connection_id, dht_public_key, timestamp); - } - - timestamp = get_connection_dht_key(m->net_crypto, m->friendlist[i].crypt_connection_id, dht_public_key); - - if (timestamp != 0) { - onion_set_friend_DHT_pubkey(m->onion_c, m->friendlist[i].onion_friendnum, dht_public_key, timestamp); + if (timestamp1 > timestamp2) { + set_connection_dht_public_key(m->net_crypto, m->friendlist[i].crypt_connection_id, dht_public_key1, timestamp1); + } else if (timestamp1 < timestamp2) { + onion_set_friend_DHT_pubkey(m->onion_c, m->friendlist[i].onion_friendnum, dht_public_key2, timestamp2); } uint8_t direct_connected; diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c index 9091900f..5abb7232 100644 --- a/toxcore/TCP_client.c +++ b/toxcore/TCP_client.c @@ -604,6 +604,9 @@ void do_TCP_connection(TCP_Client_Connection *TCP_connection) */ void kill_TCP_connection(TCP_Client_Connection *TCP_connection) { + if (TCP_connection == NULL) + return; + kill_sock(TCP_connection->sock); memset(TCP_connection, 0, sizeof(TCP_Client_Connection)); free(TCP_connection); diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 1e3456c3..b47460bc 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -424,12 +424,18 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t i; for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { - if (conn->status_tcp[i] == 2) {/* friend is connected to this relay. */ + if (conn->status_tcp[i] == STATUS_TCP_ONLINE) {/* friend is connected to this relay. */ if (send_data(c->tcp_connections[i], conn->con_number_tcp[i], data, length) == 1) return 0; } } + for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { + if (conn->status_tcp[i] == STATUS_TCP_INVISIBLE) { + if (send_oob_packet(c->tcp_connections[i], conn->dht_public_key, data, length) == 1) + return 0; + } + } return -1; } @@ -1461,9 +1467,9 @@ static int disconnect_peer_tcp(Net_Crypto *c, int crypt_connection_id) uint32_t i; for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { - if (conn->status_tcp[i]) { + if (conn->status_tcp[i] != STATUS_TCP_NULL) { send_disconnect_request(c->tcp_connections[i], conn->con_number_tcp[i]); - conn->status_tcp[i] = 0; + conn->status_tcp[i] = STATUS_TCP_NULL; conn->con_number_tcp[i] = 0; } } @@ -1575,9 +1581,10 @@ int set_direct_ip_port(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port) if (!ipport_equal(&ip_port, &conn->ip_port)) { conn->ip_port = ip_port; conn->direct_lastrecv_time = 0; + return 0; } - return 0; + return -1; } static int tcp_response_callback(void *object, uint8_t connection_id, uint8_t *public_key) @@ -1605,8 +1612,17 @@ static int tcp_response_callback(void *object, uint8_t connection_id, uint8_t *p if (c->tcp_connections[location] != TCP_con) return -1; - conn->status_tcp[location] = 1; conn->con_number_tcp[location] = connection_id; + uint32_t i; + + for (i = 0; i < conn->num_tcp_relays; ++i) { + if (memcmp(TCP_con->public_key, conn->tcp_relays[i].client_id, crypto_box_PUBLICKEYBYTES) == 0) { + conn->status_tcp[location] = STATUS_TCP_INVISIBLE; + return 0; + } + } + + conn->status_tcp[location] = STATUS_TCP_OFFLINE; return 0; } @@ -1628,13 +1644,19 @@ static int tcp_status_callback(void *object, uint32_t number, uint8_t connection if (c->tcp_connections[location] != TCP_con) return -1; - conn->status_tcp[location] = status; + if (status == 1) { + conn->status_tcp[location] = STATUS_TCP_OFFLINE; + } else if (status == 2) { + conn->status_tcp[location] = STATUS_TCP_ONLINE; + } + conn->con_number_tcp[location] = connection_id; return 0; } static int tcp_data_callback(void *object, uint32_t number, uint8_t connection_id, uint8_t *data, uint16_t length) { + if (length == 0) return -1; @@ -1729,6 +1751,56 @@ static int tcp_connection_check(Net_Crypto *c, uint8_t *public_key) return 0; } +/* Add a tcp relay, associating it to a crypt_connection_id. + * + * return 0 if it was added. + * return -1 if it wasn't. + */ +int add_tcp_relay_peer(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port, uint8_t *public_key) +{ + Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); + + if (conn == 0) + return -1; + + if (ip_port.ip.family == TCP_INET) { + ip_port.ip.family = AF_INET; + } else if (ip_port.ip.family == TCP_INET6) { + ip_port.ip.family = AF_INET6; + } + + uint32_t i; + + for (i = 0; i < conn->num_tcp_relays; ++i) { + if (memcmp(conn->tcp_relays[i].client_id, public_key, crypto_box_PUBLICKEYBYTES) == 0) { + conn->tcp_relays[i].ip_port = ip_port; + return 0; + } + } + + if (conn->num_tcp_relays == MAX_TCP_RELAYS_PEER) { + uint16_t index = rand() % MAX_TCP_RELAYS_PEER; + conn->tcp_relays[index].ip_port = ip_port; + memcpy(conn->tcp_relays[index].client_id, public_key, crypto_box_PUBLICKEYBYTES); + } else { + conn->tcp_relays[conn->num_tcp_relays].ip_port = ip_port; + memcpy(conn->tcp_relays[conn->num_tcp_relays].client_id, public_key, crypto_box_PUBLICKEYBYTES); + ++conn->num_tcp_relays; + } + + for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { + if (c->tcp_connections[i] == NULL) + continue; + + if (memcmp(c->tcp_connections[i]->public_key, public_key, crypto_box_PUBLICKEYBYTES) == 0) { + if (conn->status_tcp[i] == STATUS_TCP_OFFLINE) + conn->status_tcp[i] = STATUS_TCP_INVISIBLE; + } + } + + return add_tcp_relay(c, ip_port, public_key); +} + /* Add a tcp relay to the array. * * return 0 if it was added. @@ -1834,7 +1906,7 @@ static void clear_disconnected_tcp_peer(Crypto_Connection *conn, uint32_t number if (number >= MAX_TCP_CONNECTIONS) return; - conn->status_tcp[number] = 0; + conn->status_tcp[number] = STATUS_TCP_NULL; conn->con_number_tcp[number] = 0; } @@ -2255,6 +2327,11 @@ void kill_net_crypto(Net_Crypto *c) crypto_kill(c, i); } + for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { + kill_TCP_connection(c->tcp_connections_new[i]); + kill_TCP_connection(c->tcp_connections[i]); + } + networking_registerhandler(c->dht->net, NET_PACKET_COOKIE_REQUEST, NULL, NULL); networking_registerhandler(c->dht->net, NET_PACKET_COOKIE_RESPONSE, NULL, NULL); networking_registerhandler(c->dht->net, NET_PACKET_CRYPTO_HS, NULL, NULL); diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index e41e7e1d..14b14229 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -61,7 +61,13 @@ #define CRYPTO_RESERVED_PACKETS 16 -#define MAX_TCP_CONNECTIONS 8 +#define MAX_TCP_CONNECTIONS 32 +#define MAX_TCP_RELAYS_PEER 4 + +#define STATUS_TCP_NULL 0 +#define STATUS_TCP_OFFLINE 1 +#define STATUS_TCP_INVISIBLE 2 /* we know the other peer is connected to this relay but he isn't appearing online */ +#define STATUS_TCP_ONLINE 3 typedef struct { uint64_t time; @@ -127,8 +133,11 @@ typedef struct { uint8_t killed; /* set to 1 to kill the connection. */ - uint8_t status_tcp[MAX_TCP_CONNECTIONS]; + uint8_t status_tcp[MAX_TCP_CONNECTIONS]; /* set to one of STATUS_TCP_* */ uint8_t con_number_tcp[MAX_TCP_CONNECTIONS]; + + Node_format tcp_relays[MAX_TCP_RELAYS_PEER]; + uint16_t num_tcp_relays; } Crypto_Connection; typedef struct { @@ -244,6 +253,13 @@ uint32_t crypto_num_free_sendqueue_slots(Net_Crypto *c, int crypt_connection_id) */ int64_t write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length); +/* Add a tcp relay, associating it to a crypt_connection_id. + * + * return 0 if it was added. + * return -1 if it wasn't. + */ +int add_tcp_relay_peer(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port, uint8_t *public_key); + /* Add a tcp relay to the array. * * return 0 if it was added. diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index be4d12aa..7fab76a7 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c @@ -830,6 +830,7 @@ int onion_set_friend_DHT_pubkey(Onion_Client *onion_c, int friend_num, uint8_t * return -1; } + onion_c->friends_list[friend_num].last_seen = unix_time(); onion_c->friends_list[friend_num].is_fake_clientid = 1; onion_c->friends_list[friend_num].fake_client_id_timestamp = timestamp; memcpy(onion_c->friends_list[friend_num].fake_client_id, dht_key, crypto_box_PUBLICKEYBYTES); From 8be6b0986dadee88c2c7506cfcb41a332127add9 Mon Sep 17 00:00:00 2001 From: Maxim Biro Date: Sat, 17 May 2014 20:49:42 -0400 Subject: [PATCH 096/117] Extracted min and max allowed port values into named constants --- other/bootstrap_daemon/tox_bootstrap_daemon.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/other/bootstrap_daemon/tox_bootstrap_daemon.c b/other/bootstrap_daemon/tox_bootstrap_daemon.c index 8d3ed94a..dce181a4 100644 --- a/other/bootstrap_daemon/tox_bootstrap_daemon.c +++ b/other/bootstrap_daemon/tox_bootstrap_daemon.c @@ -62,6 +62,9 @@ #define DEFAULT_ENABLE_LAN_DISCOVERY 1 // 1 - true, 0 - false #define DEFAULT_ENABLE_TCP_RELAY 1 +#define MIN_ALLOWED_PORT 1 +#define MAX_ALLOWED_PORT 65535 + // Uses the already existing key or creates one if it didn't exist // @@ -156,8 +159,8 @@ void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_ports, int } (*tcp_relay_ports)[*tcp_relay_port_count] = config_setting_get_int(elem); - if ((*tcp_relay_ports)[i] < 1 || (*tcp_relay_ports)[i] > 65535) { - syslog(LOG_WARNING, "Port #%d: Invalid port value, should be in [1, 65535]. Skipping.\n", i); + if ((*tcp_relay_ports)[i] < MIN_ALLOWED_PORT || (*tcp_relay_ports)[i] > MAX_ALLOWED_PORT) { + syslog(LOG_WARNING, "Port #%d: Invalid port value, should be in [%d, %d]. Skipping.\n", i, MIN_ALLOWED_PORT, MAX_ALLOWED_PORT); continue; } @@ -359,9 +362,8 @@ int bootstrap_from_config(char *cfg_file_path, DHT *dht, int enable_ipv6) goto next; } - // not (1 <= port <= 65535) - if (bs_port < 1 || bs_port > 65535) { - syslog(LOG_WARNING, "Bootstrap node #%d: Invalid '%s': %d. Skipping the node.\n", i, NAME_PORT, bs_port); + if (bs_port < MIN_ALLOWED_PORT || bs_port > MAX_ALLOWED_PORT) { + syslog(LOG_WARNING, "Bootstrap node #%d: Invalid '%s': %d, should be in [%d, %d]. Skipping the node.\n", i, NAME_PORT, bs_port, MIN_ALLOWED_PORT, MAX_ALLOWED_PORT); goto next; } @@ -437,9 +439,8 @@ int main(int argc, char *argv[]) return 1; } - // not (1 <= port <= 65535) - if (port < 1 || port > 65535) { - syslog(LOG_ERR, "Invalid port: %d, must be 1 <= port <= 65535. Exiting.\n", port); + if (port < MIN_ALLOWED_PORT || port > MAX_ALLOWED_PORT) { + syslog(LOG_ERR, "Invalid port: %d, should be in [%d, %d]. Exiting.\n", port, MIN_ALLOWED_PORT, MAX_ALLOWED_PORT); return 1; } From e75930e72e40a69aea94240415af9ca53604ad0e Mon Sep 17 00:00:00 2001 From: Maxim Biro Date: Sat, 17 May 2014 20:50:17 -0400 Subject: [PATCH 097/117] Some small fixes --- other/bootstrap_daemon/tox_bootstrap_daemon.c | 29 +++++++++---------- .../bootstrap_daemon/tox_bootstrap_daemon.sh | 4 +-- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/other/bootstrap_daemon/tox_bootstrap_daemon.c b/other/bootstrap_daemon/tox_bootstrap_daemon.c index dce181a4..410a3453 100644 --- a/other/bootstrap_daemon/tox_bootstrap_daemon.c +++ b/other/bootstrap_daemon/tox_bootstrap_daemon.c @@ -50,6 +50,7 @@ // misc #include "../../testing/misc_tools.c" + #define DAEMON_NAME "tox_bootstrap_daemon" #define SLEEP_TIME_MILLISECONDS 30 @@ -60,7 +61,7 @@ #define DEFAULT_PORT 33445 #define DEFAULT_ENABLE_IPV6 0 // 1 - true, 0 - false #define DEFAULT_ENABLE_LAN_DISCOVERY 1 // 1 - true, 0 - false -#define DEFAULT_ENABLE_TCP_RELAY 1 +#define DEFAULT_ENABLE_TCP_RELAY 1 // 1 - true, 0 - false #define MIN_ALLOWED_PORT 1 #define MAX_ALLOWED_PORT 65535 @@ -356,7 +357,7 @@ int bootstrap_from_config(char *cfg_file_path, DHT *dht, int enable_ipv6) } // Process settings - if (strlen(bs_public_key) != 64) { + if (strlen(bs_public_key) != crypto_box_PUBLICKEYBYTES*2) { syslog(LOG_WARNING, "Bootstrap node #%d: Invalid '%s': %s. Skipping the node.\n", i, NAME_PUBLIC_KEY, bs_public_key); goto next; @@ -380,9 +381,9 @@ int bootstrap_from_config(char *cfg_file_path, DHT *dht, int enable_ipv6) syslog(LOG_DEBUG, "Successfully added bootstrap node #%d: %s:%d %s\n", i, bs_address, bs_port, bs_public_key); next: - // config_setting_lookup_string() allocates string inside and doesn't allow us to free it - // so in order to reuse `bs_public_key` and `bs_address` we have to remove the element - // which will cause libconfig to free allocated strings + // config_setting_lookup_string() allocates string inside and doesn't allow us to free it direcly + // though it's freed when the element is removed, so we free it right away in order to keep memory + // consumption minimal config_setting_remove_elem(node_list, 0); i++; } @@ -396,17 +397,13 @@ next: void print_public_key(uint8_t *public_key) { - char buffer[64 + 1]; + char buffer[2*crypto_box_PUBLICKEYBYTES + 1]; int index = 0; int i; - for (i = 0; i < 32; i++) { - if (public_key[i] < 16) { - index += sprintf(buffer + index, "0"); - } - - index += sprintf(buffer + index, "%hhX", public_key[i]); + for (i = 0; i < crypto_box_PUBLICKEYBYTES; i++) { + index += sprintf(buffer + index, "%02hhX", public_key[i]); } syslog(LOG_INFO, "Public Key: %s\n", buffer); @@ -468,10 +465,6 @@ int main(int argc, char *argv[]) return 1; } - if (enable_lan_discovery) { - LANdiscovery_init(dht); - } - if (manage_keys(dht, keys_file_path)) { syslog(LOG_DEBUG, "Keys are managed successfully\n"); } else { @@ -559,6 +552,10 @@ int main(int argc, char *argv[]) int waiting_for_dht_connection = 1; + if (enable_lan_discovery) { + LANdiscovery_init(dht); + } + while (1) { do_DHT(dht); diff --git a/other/bootstrap_daemon/tox_bootstrap_daemon.sh b/other/bootstrap_daemon/tox_bootstrap_daemon.sh index 83d9a119..e083ea0b 100644 --- a/other/bootstrap_daemon/tox_bootstrap_daemon.sh +++ b/other/bootstrap_daemon/tox_bootstrap_daemon.sh @@ -11,12 +11,12 @@ # PATH should only include /usr/* if it runs after the mountnfs.sh script PATH=/sbin:/usr/sbin:/bin:/usr/bin -DESC="Tox DHT bootstrap server daemon" +DESC="Tox DHT bootstrap daemon" NAME=tox_bootstrap_daemon # You may want to change USER if you are using it anywhere else USER=tom CFG=/home/$USER/.$NAME/conf -DAEMON=/home/$USER/$NAME +DAEMON=/home/$USER/.$NAME/$NAME DAEMON_ARGS="$CFG" PIDFILE=/home/$USER/.$NAME/pid SCRIPTNAME=/etc/init.d/$NAME From 7dd811214ad335224f554ae658ce7b4c430a40c8 Mon Sep 17 00:00:00 2001 From: Maxim Biro Date: Sat, 17 May 2014 23:57:24 -0400 Subject: [PATCH 098/117] Added MOTD functionality --- other/bootstrap_daemon/conf | 14 ++-- other/bootstrap_daemon/tox_bootstrap_daemon.c | 69 +++++++++++++++++-- 2 files changed, 72 insertions(+), 11 deletions(-) diff --git a/other/bootstrap_daemon/conf b/other/bootstrap_daemon/conf index fb524754..bbdf7652 100644 --- a/other/bootstrap_daemon/conf +++ b/other/bootstrap_daemon/conf @@ -3,7 +3,7 @@ // Listening port. port = 33445 -// The key file is like a password, so keep it where no one can read it. +// A key file is like a password, so keep it where no one can read it. // The daemon should have permission to read/write to it. // Remember to replace the provided example with your own path. keys_file_path = "/home/tom/.tox_bootstrap_daemon/keys" @@ -23,9 +23,15 @@ enable_lan_discovery = true enable_tcp_relay = true // Tox uses 443 and 3389 ports by default, so it's highly recommended to keep -// them +// them. tcp_relay_ports = [443, 3389] +// It's planned to use message of the day as a convenient method of checking +// whether a node is up or not, though there are other methods of doing that. +enable_motd = true + +motd = "tox_bootstrap_daemon" + // Any number of nodes the daemon will bootstrap itself from. // Remember to replace the provided example with your own node list. // There is a maintained list of bootstrap nodes on Tox's wiki, if you need it. @@ -34,8 +40,8 @@ tcp_relay_ports = [443, 3389] // from anyone. bootstrap_nodes = ( { // Node 1 - // Any ipv4 or ipv6, depending if `enable_ipv6` is set or not, and also - // any US-ASCII domain name. + // Any ipv4 or ipv6, depending on whether `enable_ipv6` is set or not, and + // also any US-ASCII domain name. address = "198.46.136.167" port = 33445 public_key = "728925473812C7AAC482BE7250BCCAD0B8CB9F737BF3D42ABD34459C1768F854" diff --git a/other/bootstrap_daemon/tox_bootstrap_daemon.c b/other/bootstrap_daemon/tox_bootstrap_daemon.c index 410a3453..6853358a 100644 --- a/other/bootstrap_daemon/tox_bootstrap_daemon.c +++ b/other/bootstrap_daemon/tox_bootstrap_daemon.c @@ -48,10 +48,12 @@ #include "../../toxcore/util.h" // misc +#include "../bootstrap_node_packets.c" #include "../../testing/misc_tools.c" #define DAEMON_NAME "tox_bootstrap_daemon" +#define DAEMON_VERSION_NUMBER 2014051700UL // yyyymmmddvv format: yyyy year, mm month, dd day, vv version change count for that day #define SLEEP_TIME_MILLISECONDS 30 #define sleep usleep(1000*SLEEP_TIME_MILLISECONDS) @@ -62,6 +64,8 @@ #define DEFAULT_ENABLE_IPV6 0 // 1 - true, 0 - false #define DEFAULT_ENABLE_LAN_DISCOVERY 1 // 1 - true, 0 - false #define DEFAULT_ENABLE_TCP_RELAY 1 // 1 - true, 0 - false +#define DEFAULT_ENABLE_MOTD 1 // 1 - true, 0 - false +#define DEFAULT_MOTD DAEMON_NAME #define MIN_ALLOWED_PORT 1 #define MAX_ALLOWED_PORT 65535 @@ -129,7 +133,7 @@ void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_ports, int } if (config_setting_is_array(ports_array) == CONFIG_FALSE) { - syslog(LOG_WARNING, "'%s' setting should be an array. Array syntax: 'setting = [value1, value2, ...]'.\n"); + syslog(LOG_WARNING, "'%s' setting should be an array. Array syntax: 'setting = [value1, value2, ...]'.\n", NAME_TCP_RELAY_PORTS); return; } @@ -161,7 +165,7 @@ void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_ports, int (*tcp_relay_ports)[*tcp_relay_port_count] = config_setting_get_int(elem); if ((*tcp_relay_ports)[i] < MIN_ALLOWED_PORT || (*tcp_relay_ports)[i] > MAX_ALLOWED_PORT) { - syslog(LOG_WARNING, "Port #%d: Invalid port value, should be in [%d, %d]. Skipping.\n", i, MIN_ALLOWED_PORT, MAX_ALLOWED_PORT); + syslog(LOG_WARNING, "Port #%d: Invalid port: %u, should be in [%d, %d]. Skipping.\n", i, (*tcp_relay_ports)[i], MIN_ALLOWED_PORT, MAX_ALLOWED_PORT); continue; } @@ -176,12 +180,14 @@ void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_ports, int // // Important: you are responsible for freeing `pid_file_path` and `keys_file_path` // also, iff `tcp_relay_ports_count` > 0, then you are responsible for freeing `tcp_relay_ports` +// and also `motd` iff `enable_motd` is set // // returns 1 on success // 0 on failure, doesn't modify any data pointed by arguments int get_general_config(char *cfg_file_path, char **pid_file_path, char **keys_file_path, int *port, int *enable_ipv6, - int *enable_lan_discovery, int *enable_tcp_relay, uint16_t **tcp_relay_ports, int *tcp_relay_port_count) + int *enable_lan_discovery, int *enable_tcp_relay, uint16_t **tcp_relay_ports, int *tcp_relay_port_count, + int *enable_motd, char **motd) { config_t cfg; @@ -191,6 +197,8 @@ int get_general_config(char *cfg_file_path, char **pid_file_path, char **keys_fi const char *NAME_ENABLE_IPV6 = "enable_ipv6"; const char *NAME_ENABLE_LAN_DISCOVERY = "enable_lan_discovery"; const char *NAME_ENABLE_TCP_RELAY = "enable_tcp_relay"; + const char *NAME_ENABLE_MOTD = "enable_motd"; + const char *NAME_MOTD = "motd"; config_init(&cfg); @@ -261,6 +269,30 @@ int get_general_config(char *cfg_file_path, char **pid_file_path, char **keys_fi *tcp_relay_port_count = 0; } + // Get MOTD option + if (config_lookup_bool(&cfg, NAME_ENABLE_MOTD, enable_motd) == CONFIG_FALSE) { + syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_ENABLE_MOTD); + syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_ENABLE_MOTD, + DEFAULT_ENABLE_MOTD ? "true" : "false"); + *enable_motd = DEFAULT_ENABLE_MOTD; + } + + if (*enable_motd) { + // Get MOTD + const char *tmp_motd; + + if (config_lookup_string(&cfg, NAME_MOTD, &tmp_motd) == CONFIG_FALSE) { + syslog(LOG_WARNING, "No '%s' setting in configuration file.\n", NAME_MOTD); + syslog(LOG_WARNING, "Using default '%s': %s\n", NAME_MOTD, DEFAULT_MOTD); + tmp_motd = DEFAULT_MOTD; + } + size_t tmp_motd_length = strlen(tmp_motd) + 1; + size_t motd_length = tmp_motd_length > MAX_MOTD_LENGTH ? MAX_MOTD_LENGTH : tmp_motd_length; + *motd = malloc(motd_length); + strncpy(*motd, tmp_motd, motd_length); + (*motd)[MAX_MOTD_LENGTH - 1] = '\0'; + } + config_destroy(&cfg); syslog(LOG_DEBUG, "Successfully read:\n"); @@ -269,6 +301,7 @@ int get_general_config(char *cfg_file_path, char **pid_file_path, char **keys_fi syslog(LOG_DEBUG, "'%s': %d\n", NAME_PORT, *port); syslog(LOG_DEBUG, "'%s': %s\n", NAME_ENABLE_IPV6, *enable_ipv6 ? "true" : "false"); syslog(LOG_DEBUG, "'%s': %s\n", NAME_ENABLE_LAN_DISCOVERY, *enable_lan_discovery ? "true" : "false"); + syslog(LOG_DEBUG, "'%s': %s\n", NAME_ENABLE_TCP_RELAY, *enable_tcp_relay ? "true" : "false"); // show info about tcp ports only if tcp relay is enabled if (*enable_tcp_relay) { @@ -283,6 +316,11 @@ int get_general_config(char *cfg_file_path, char **pid_file_path, char **keys_fi } } + syslog(LOG_DEBUG, "'%s': %s\n", NAME_ENABLE_MOTD, *enable_motd ? "true" : "false"); + if (*enable_motd) { + syslog(LOG_DEBUG, "'%s': %s\n", NAME_MOTD, *motd); + } + return 1; } @@ -415,6 +453,8 @@ int main(int argc, char *argv[]) { openlog(DAEMON_NAME, LOG_NOWAIT | LOG_PID, LOG_DAEMON); + syslog(LOG_INFO, "Running \"%s\" version %lu.\n", DAEMON_NAME, DAEMON_VERSION_NUMBER); + if (argc < 2) { syslog(LOG_ERR, "Please specify a path to a configuration file as the first argument. Exiting.\n"); return 1; @@ -428,8 +468,10 @@ int main(int argc, char *argv[]) int enable_tcp_relay; uint16_t *tcp_relay_ports; int tcp_relay_port_count; + int enable_motd; + char *motd; - if (get_general_config(cfg_file_path, &pid_file_path, &keys_file_path, &port, &enable_ipv6, &enable_lan_discovery, &enable_tcp_relay, &tcp_relay_ports, &tcp_relay_port_count)) { + if (get_general_config(cfg_file_path, &pid_file_path, &keys_file_path, &port, &enable_ipv6, &enable_lan_discovery, &enable_tcp_relay, &tcp_relay_ports, &tcp_relay_port_count, &enable_motd, &motd)) { syslog(LOG_DEBUG, "General config read successfully\n"); } else { syslog(LOG_ERR, "Couldn't read config file: %s. Exiting.\n", cfg_file_path); @@ -465,8 +507,18 @@ int main(int argc, char *argv[]) return 1; } + if (enable_motd) { + if (bootstrap_set_callbacks(dht->net, DAEMON_VERSION_NUMBER, (uint8_t*)motd, strlen(motd) + 1) == 0) { + syslog(LOG_DEBUG, "Set MOTD successfully.\n"); + } else { + syslog(LOG_ERR, "Couldn't set MOTD: %s. Exiting.\n", motd); + return 1; + } + free(motd); + } + if (manage_keys(dht, keys_file_path)) { - syslog(LOG_DEBUG, "Keys are managed successfully\n"); + syslog(LOG_DEBUG, "Keys are managed successfully.\n"); } else { syslog(LOG_ERR, "Couldn't read/write: %s. Exiting.\n", keys_file_path); return 1; @@ -485,14 +537,16 @@ int main(int argc, char *argv[]) // tcp_relay_port_count != 0 at this point free(tcp_relay_ports); - if (tcp_server == NULL) { + if (tcp_server != NULL) { + syslog(LOG_DEBUG, "Initialized Tox TCP server successfully.\n"); + } else { syslog(LOG_ERR, "Couldn't initialize Tox TCP server. Exiting.\n"); return 1; } } if (bootstrap_from_config(cfg_file_path, dht, enable_ipv6)) { - syslog(LOG_DEBUG, "List of bootstrap nodes read successfully\n"); + syslog(LOG_DEBUG, "List of bootstrap nodes read successfully.\n"); } else { syslog(LOG_ERR, "Couldn't read list of bootstrap nodes in %s. Exiting.\n", cfg_file_path); return 1; @@ -554,6 +608,7 @@ int main(int argc, char *argv[]) if (enable_lan_discovery) { LANdiscovery_init(dht); + syslog(LOG_DEBUG, "Initialized LAN discovery.\n"); } while (1) { From e87929e869d3d63eb4800d1c74daf099e2f0a264 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sun, 18 May 2014 10:55:38 -0400 Subject: [PATCH 099/117] TCP branch now ready for start of real testing. Friends can now exchange TCP relay addresses so that they can connect together. Currently all bootstrap nodes are treated as TCP relays. --- toxcore/Messenger.c | 17 +++++++++++++++++ toxcore/TCP_client.c | 1 + toxcore/TCP_client.h | 1 + toxcore/net_crypto.c | 35 +++++++++++++++++++++++++++++++++++ toxcore/net_crypto.h | 8 ++++++++ toxcore/onion_client.c | 39 +++++++++++++++++++++++++++++++++++---- toxcore/onion_client.h | 15 +++++++++++++++ toxcore/tox.c | 28 +++++++++++++++++++++++++++- 8 files changed, 139 insertions(+), 5 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 472c2ae4..f53a1d04 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -195,6 +195,21 @@ void getaddress(Messenger *m, uint8_t *address) memcpy(address + crypto_box_PUBLICKEYBYTES + sizeof(nospam), &checksum, sizeof(checksum)); } +/* callback for recv TCP relay nodes. */ +static int tcp_relay_node_callback(void *object, uint32_t number, IP_Port ip_port, uint8_t *public_key) +{ + Messenger *m = object; + + if (friend_not_valid(m, number)) + return -1; + + if (m->friendlist[number].crypt_connection_id != -1) { + return add_tcp_relay_peer(m->net_crypto, m->friendlist[number].crypt_connection_id, ip_port, public_key); + } else { + return add_tcp_relay(m->net_crypto, ip_port, public_key); + } +} + /* * Add a friend. * Set the data that will be sent along with friend request. @@ -277,6 +292,7 @@ int32_t m_addfriend(Messenger *m, uint8_t *address, uint8_t *data, uint16_t leng m->friendlist[i].message_id = 0; m->friendlist[i].receives_read_receipts = 1; /* Default: YES. */ memcpy(&(m->friendlist[i].friendrequest_nospam), address + crypto_box_PUBLICKEYBYTES, sizeof(uint32_t)); + recv_tcp_relay_handler(m->onion_c, onion_friendnum, &tcp_relay_node_callback, m, i); if (m->numfriends == i) ++m->numfriends; @@ -322,6 +338,7 @@ int32_t m_addfriend_norequest(Messenger *m, uint8_t *client_id) m->friendlist[i].is_typing = 0; m->friendlist[i].message_id = 0; m->friendlist[i].receives_read_receipts = 1; /* Default: YES. */ + recv_tcp_relay_handler(m->onion_c, onion_friendnum, &tcp_relay_node_callback, m, i); if (m->numfriends == i) ++m->numfriends; diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c index 5abb7232..e1b460ab 100644 --- a/toxcore/TCP_client.c +++ b/toxcore/TCP_client.c @@ -372,6 +372,7 @@ TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, uint8_t *public_key, temp->status = TCP_CLIENT_CONNECTING; temp->sock = sock; memcpy(temp->public_key, public_key, crypto_box_PUBLICKEYBYTES); + temp->ip_port = ip_port; if (generate_handshake(temp, self_public_key, self_secret_key) == -1) { kill_sock(sock); diff --git a/toxcore/TCP_client.h b/toxcore/TCP_client.h index 9583e15f..afb95392 100644 --- a/toxcore/TCP_client.h +++ b/toxcore/TCP_client.h @@ -40,6 +40,7 @@ typedef struct { uint8_t status; sock_t sock; uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* public key of the server */ + IP_Port ip_port; /* The ip and port of the server */ uint8_t recv_nonce[crypto_box_NONCEBYTES]; /* Nonce of received packets. */ uint8_t sent_nonce[crypto_box_NONCEBYTES]; /* Nonce of sent packets. */ uint8_t shared_key[crypto_box_BEFORENMBYTES]; diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index b47460bc..7cbac43b 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -1823,6 +1823,41 @@ int add_tcp_relay(Net_Crypto *c, IP_Port ip_port, uint8_t *public_key) return -1; } +/* Copy a maximum of num TCP relays we are connected to to tcp_relays. + * NOTE that the family of the copied ip ports will be set to TCP_INET or TCP_INET6. + * + * return number of relays copied to tcp_relays on success. + * return 0 on failure. + */ +unsigned int copy_connected_tcp_relays(Net_Crypto *c, Node_format *tcp_relays, uint16_t num) +{ + if (num == 0) + return 0; + + uint32_t i; + uint16_t copied = 0; + + for (i = 0; i < MAX_TCP_CONNECTIONS; ++i) { + if (c->tcp_connections[i] != NULL) { + memcpy(tcp_relays[copied].client_id, c->tcp_connections[i]->public_key, crypto_box_PUBLICKEYBYTES); + tcp_relays[copied].ip_port = c->tcp_connections[i]->ip_port; + + if (tcp_relays[copied].ip_port.ip.family == AF_INET) { + tcp_relays[copied].ip_port.ip.family = TCP_INET; + } else if (tcp_relays[copied].ip_port.ip.family == AF_INET6) { + tcp_relays[copied].ip_port.ip.family = TCP_INET6; + } + + ++copied; + + if (copied == num) + return copied; + } + } + + return copied; +} + /* Add a connected tcp connection to the tcp_connections array. * * return 0 if it was added. diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index 14b14229..25f8c2f7 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -267,6 +267,14 @@ int add_tcp_relay_peer(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port, */ int add_tcp_relay(Net_Crypto *c, IP_Port ip_port, uint8_t *public_key); +/* Copy a maximum of num TCP relays we are connected to to tcp_relays. + * NOTE that the family of the copied ip ports will be set to TCP_INET or TCP_INET6. + * + * return number of relays copied to tcp_relays on success. + * return 0 on failure. + */ +unsigned int copy_connected_tcp_relays(Net_Crypto *c, Node_format *tcp_relays, uint16_t num); + /* Kill a crypto connection. * * return -1 on failure. diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index 7fab76a7..03ffbaa7 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c @@ -505,7 +505,7 @@ static int handle_fakeid_announce(void *object, uint8_t *source_pubkey, uint8_t if (len_nodes != 0) { Node_format nodes[MAX_SENT_NODES]; int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, 0, data + 1 + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES, - len_nodes, 0); + len_nodes, 1); if (num_nodes <= 0) return 1; @@ -513,7 +513,17 @@ static int handle_fakeid_announce(void *object, uint8_t *source_pubkey, uint8_t int i; for (i = 0; i < num_nodes; ++i) { - DHT_getnodes(onion_c->dht, &nodes[i].ip_port, nodes[i].client_id, onion_c->friends_list[friend_num].fake_client_id); + uint8_t family = nodes[i].ip_port.ip.family; + + if (family == AF_INET || family == AF_INET6) { + DHT_getnodes(onion_c->dht, &nodes[i].ip_port, nodes[i].client_id, onion_c->friends_list[friend_num].fake_client_id); + } else if (family == TCP_INET || family == TCP_INET6) { + if (onion_c->friends_list[friend_num].tcp_relay_node_callback) { + void *obj = onion_c->friends_list[friend_num].tcp_relay_node_callback_object; + uint32_t number = onion_c->friends_list[friend_num].tcp_relay_node_callback_number; + onion_c->friends_list[friend_num].tcp_relay_node_callback(obj, number, nodes[i].ip_port, nodes[i].client_id); + } + } } } @@ -664,8 +674,9 @@ static int send_fakeid_announce(Onion_Client *onion_c, uint16_t friend_num, uint 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); - + uint16_t num_relays = copy_connected_tcp_relays(onion_c->c, nodes, (MAX_SENT_NODES / 2)); + uint16_t num_nodes = closelist_nodes(onion_c->dht, &nodes[num_relays], MAX_SENT_NODES - num_relays); + num_nodes += num_relays; int nodes_len = 0; if (num_nodes != 0) { @@ -800,6 +811,26 @@ int onion_delfriend(Onion_Client *onion_c, int friend_num) return friend_num; } +/* Set the function for this friend that will be callbacked with object and number + * when that friends gives us one of the TCP relays he is connected to. + * + * object and number will be passed as argument to this function. + * + * return -1 on failure. + * return 0 on success. + */ +int recv_tcp_relay_handler(Onion_Client *onion_c, int friend_num, int (*tcp_relay_node_callback)(void *object, + uint32_t number, IP_Port ip_port, uint8_t *public_key), void *object, uint32_t number) +{ + if ((uint32_t)friend_num >= onion_c->num_friends) + return -1; + + onion_c->friends_list[friend_num].tcp_relay_node_callback = tcp_relay_node_callback; + onion_c->friends_list[friend_num].tcp_relay_node_callback_object = object; + onion_c->friends_list[friend_num].tcp_relay_node_callback_number = number; + return 0; +} + /* Set a friends DHT public key. * timestamp is the time (current_time_monotonic()) at which the key was last confirmed belonging to * the other peer. diff --git a/toxcore/onion_client.h b/toxcore/onion_client.h index 029f5624..0d2e84a5 100644 --- a/toxcore/onion_client.h +++ b/toxcore/onion_client.h @@ -102,6 +102,10 @@ typedef struct { Last_Pinged last_pinged[MAX_STORED_PINGED_NODES]; uint8_t last_pinged_index; + + int (*tcp_relay_node_callback)(void *object, uint32_t number, IP_Port ip_port, uint8_t *public_key); + void *tcp_relay_node_callback_object; + uint32_t tcp_relay_node_callback_number; } Onion_Friend; typedef int (*oniondata_handler_callback)(void *object, uint8_t *source_pubkey, uint8_t *data, uint32_t len); @@ -176,6 +180,17 @@ int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_on */ int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port); +/* Set the function for this friend that will be callbacked with object and number + * when that friends gives us one of the TCP relays he is connected to. + * + * object and number will be passed as argument to this function. + * + * return -1 on failure. + * return 0 on success. + */ +int recv_tcp_relay_handler(Onion_Client *onion_c, int friend_num, int (*tcp_relay_node_callback)(void *object, + uint32_t number, IP_Port ip_port, uint8_t *public_key), void *object, uint32_t number); + /* Set a friends DHT public key. * timestamp is the time (current_time_monotonic()) at which the key was last confirmed belonging to * the other peer. diff --git a/toxcore/tox.c b/toxcore/tox.c index d86f1a17..083582bb 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -739,12 +739,38 @@ uint64_t tox_file_data_remaining(Tox *tox, int32_t friendnumber, uint8_t filenum /***************END OF FILE SENDING FUNCTIONS******************/ +/* TODO: expose this properly. */ +static int tox_add_tcp_relay(Tox *tox, const char *address, uint8_t ipv6enabled, uint16_t port, uint8_t *public_key) +{ + Messenger *m = tox; + IP_Port ip_port_v64; + IP *ip_extra = NULL; + IP_Port ip_port_v4; + ip_init(&ip_port_v64.ip, ipv6enabled); + + if (ipv6enabled) { + /* setup for getting BOTH: an IPv6 AND an IPv4 address */ + ip_port_v64.ip.family = AF_UNSPEC; + ip_reset(&ip_port_v4.ip); + ip_extra = &ip_port_v4.ip; + } + + if (addr_resolve_or_parse_ip(address, &ip_port_v64.ip, ip_extra)) { + ip_port_v64.port = port; + add_tcp_relay(m->net_crypto, ip_port_v64, public_key); + return 1; + } else { + return 0; + } +} + int tox_bootstrap_from_address(Tox *tox, const char *address, uint8_t ipv6enabled, uint16_t port, uint8_t *public_key) { Messenger *m = tox; + tox_add_tcp_relay(tox, address, ipv6enabled, port, public_key); return DHT_bootstrap_from_address(m->dht, address, ipv6enabled, port, public_key); -}; +} /* return 0 if we are not connected to the DHT. * return 1 if we are. From d573271f0359cd084cf3de6f13b3b1bf87fa0d2d Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sun, 18 May 2014 12:15:57 -0400 Subject: [PATCH 100/117] Fixed connection issue. --- toxcore/net_crypto.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 7cbac43b..1fcd434e 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -406,6 +406,8 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, uint8_t *data, if (conn == 0) return -1; + int direct_send_attempt = 0; + //TODO: on bad networks, direct connections might not last indefinitely. if (conn->ip_port.ip.family != 0) { uint8_t direct_connected = 0; @@ -415,8 +417,10 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, uint8_t *data, return 0; //TODO: a better way of sending packets directly to confirm the others ip. - if (length < 96 || data[0] == NET_PACKET_COOKIE_REQUEST || data[0] == NET_PACKET_CRYPTO_HS) - sendpacket(c->dht->net, conn->ip_port, data, length); + if (length < 96 || data[0] == NET_PACKET_COOKIE_REQUEST || data[0] == NET_PACKET_CRYPTO_HS) { + if ((uint32_t)sendpacket(c->dht->net, conn->ip_port, data, length) == length) + direct_send_attempt = 1; + } } @@ -436,6 +440,11 @@ static int send_packet_to(Net_Crypto *c, int crypt_connection_id, uint8_t *data, return 0; } } + + if (direct_send_attempt) { + return 0; + } + return -1; } From 8cb3ddda8b42441f135df38e283ac3c3d1d075a4 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sun, 18 May 2014 12:59:21 -0400 Subject: [PATCH 101/117] Fixed TCP client connection isse. --- toxcore/TCP_client.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c index e1b460ab..00a11472 100644 --- a/toxcore/TCP_client.c +++ b/toxcore/TCP_client.c @@ -446,6 +446,9 @@ static int handle_TCP_packet(TCP_Client_Connection *conn, uint8_t *data, uint16_ uint8_t con_id = data[1] - NUM_RESERVED_PORTS; + if (conn->connections[con_id].status == 0) + return 0; + if (conn->connections[con_id].status != 2) return -1; From d68197b8955066be83b79d7b9f823de03e83565a Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sun, 18 May 2014 13:45:33 -0400 Subject: [PATCH 102/117] Save a couple TCP relays on save and reconnect to them on load. Removed some old code. --- toxcore/Messenger.c | 101 ++++++++++++------------------------------- toxcore/net_crypto.c | 12 +++++ 2 files changed, 40 insertions(+), 73 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index f53a1d04..96005237 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -2477,9 +2477,10 @@ int wait_cleanup_messenger(Messenger *m, uint8_t *data) #define MESSENGER_STATE_TYPE_NAME 4 #define MESSENGER_STATE_TYPE_STATUSMESSAGE 5 #define MESSENGER_STATE_TYPE_STATUS 6 +#define MESSENGER_STATE_TYPE_TCP_RELAY 10 #define SAVED_FRIEND_REQUEST_SIZE 1024 - +#define NUM_SAVED_TCP_RELAYS 8 struct SAVED_FRIEND { uint8_t status; uint8_t client_id[CLIENT_ID_SIZE]; @@ -2614,6 +2615,7 @@ uint32_t messenger_size(Messenger *m) + sizesubhead + m->name_length // Own nickname. + sizesubhead + m->statusmessage_length // status message + sizesubhead + 1 // status + + sizesubhead + NUM_SAVED_TCP_RELAYS * sizeof(Node_format) //TCP relays ; } @@ -2678,74 +2680,15 @@ void messenger_save(Messenger *m, uint8_t *data) data = z_state_save_subheader(data, len, type); *data = m->userstatus; data += len; -} -static int messenger_load_state_callback_old(void *outer, uint8_t *data, uint32_t length, uint16_t type) -{ - Messenger *m = outer; - - switch (type) { - case MESSENGER_STATE_TYPE_NOSPAMKEYS: - 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 */ - - break; - - case MESSENGER_STATE_TYPE_DHT: - DHT_load(m->dht, data, length); - break; - - case MESSENGER_STATE_TYPE_FRIENDS: - if (!(length % sizeof(Friend))) { - uint16_t num = length / sizeof(Friend); - Friend *friends = (Friend *)data; - uint32_t i; - - for (i = 0; i < num; ++i) { - if (friends[i].status >= 3) { - int fnum = m_addfriend_norequest(m, friends[i].client_id); - setfriendname(m, fnum, friends[i].name, friends[i].name_length); - /* set_friend_statusmessage(fnum, temp[i].statusmessage, temp[i].statusmessage_length); */ - } else if (friends[i].status != 0) { - /* TODO: This is not a good way to do this. */ - uint8_t address[FRIEND_ADDRESS_SIZE]; - id_copy(address, friends[i].client_id); - memcpy(address + crypto_box_PUBLICKEYBYTES, &(friends[i].friendrequest_nospam), sizeof(uint32_t)); - uint16_t checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum)); - memcpy(address + crypto_box_PUBLICKEYBYTES + sizeof(uint32_t), &checksum, sizeof(checksum)); - m_addfriend(m, address, friends[i].info, friends[i].info_size); - } - } - } - - break; - - case MESSENGER_STATE_TYPE_NAME: - if ((length > 0) && (length < MAX_NAME_LENGTH)) { - setname(m, data, length); - } - - break; - -#ifdef DEBUG - - default: - fprintf(stderr, "Load state: contains unrecognized part (len %u, type %u)\n", - length, type); - break; -#endif - } - - return 0; + Node_format relays[NUM_SAVED_TCP_RELAYS]; + len = sizeof(relays); + type = MESSENGER_STATE_TYPE_TCP_RELAY; + data = z_state_save_subheader(data, len, type); + memset(relays, 0, len); + copy_connected_tcp_relays(m->net_crypto, relays, NUM_SAVED_TCP_RELAYS); + memcpy(data, relays, len); + data += len; } static int messenger_load_state_callback(void *outer, uint8_t *data, uint32_t length, uint16_t type) @@ -2796,6 +2739,22 @@ static int messenger_load_state_callback(void *outer, uint8_t *data, uint32_t le } break; + + case MESSENGER_STATE_TYPE_TCP_RELAY: { + Node_format relays[NUM_SAVED_TCP_RELAYS]; + + if (length != sizeof(relays)) { + return -1; + } + + memcpy(relays, data, length); + uint32_t i; + + for (i = 0; i < NUM_SAVED_TCP_RELAYS; ++i) { + add_tcp_relay(m->net_crypto, relays[i].ip_port, relays[i].client_id); + } + } + break; #ifdef DEBUG default: @@ -2822,11 +2781,7 @@ int messenger_load(Messenger *m, uint8_t *data, uint32_t length) if (!data32[0] && (data32[1] == MESSENGER_STATE_COOKIE_GLOBAL)) return load_state(messenger_load_state_callback, m, data + cookie_len, length - cookie_len, MESSENGER_STATE_COOKIE_TYPE); - - else if (!data32[0] && (data32[1] == MESSENGER_STATE_COOKIE_GLOBAL_OLD)) - return load_state(messenger_load_state_callback_old, m, data + cookie_len, - length - cookie_len, MESSENGER_STATE_COOKIE_TYPE); - else /* old state file */ + else return -1; } diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 1fcd434e..875c639f 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -1778,6 +1778,9 @@ int add_tcp_relay_peer(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port, ip_port.ip.family = AF_INET6; } + if (ip_port.ip.family != AF_INET && ip_port.ip.family != AF_INET6) + return -1; + uint32_t i; for (i = 0; i < conn->num_tcp_relays; ++i) { @@ -1817,6 +1820,15 @@ int add_tcp_relay_peer(Net_Crypto *c, int crypt_connection_id, IP_Port ip_port, */ int add_tcp_relay(Net_Crypto *c, IP_Port ip_port, uint8_t *public_key) { + if (ip_port.ip.family == TCP_INET) { + ip_port.ip.family = AF_INET; + } else if (ip_port.ip.family == TCP_INET6) { + ip_port.ip.family = AF_INET6; + } + + if (ip_port.ip.family != AF_INET && ip_port.ip.family != AF_INET6) + return -1; + if (tcp_connection_check(c, public_key) != 0) return -1; From 376eecafd3cbb044c5651cb0cb688d9517abb633 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sun, 18 May 2014 13:58:41 -0400 Subject: [PATCH 103/117] Fixed possible connection issue. --- toxcore/TCP_client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c index 00a11472..e4845852 100644 --- a/toxcore/TCP_client.c +++ b/toxcore/TCP_client.c @@ -404,7 +404,7 @@ static int handle_TCP_packet(TCP_Client_Connection *conn, uint8_t *data, uint16_ uint8_t con_id = data[1] - NUM_RESERVED_PORTS; if (conn->connections[con_id].status != 0) - return -1; + return 0; conn->connections[con_id].status = 1; conn->connections[con_id].number = ~0; From 906969d376244fadcf188c0297df2605bf407dd5 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sun, 18 May 2014 14:43:32 -0400 Subject: [PATCH 104/117] Fixed out of bounds write. --- other/bootstrap_daemon/tox_bootstrap_daemon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/other/bootstrap_daemon/tox_bootstrap_daemon.c b/other/bootstrap_daemon/tox_bootstrap_daemon.c index 6853358a..2c8f7014 100644 --- a/other/bootstrap_daemon/tox_bootstrap_daemon.c +++ b/other/bootstrap_daemon/tox_bootstrap_daemon.c @@ -290,7 +290,7 @@ int get_general_config(char *cfg_file_path, char **pid_file_path, char **keys_fi size_t motd_length = tmp_motd_length > MAX_MOTD_LENGTH ? MAX_MOTD_LENGTH : tmp_motd_length; *motd = malloc(motd_length); strncpy(*motd, tmp_motd, motd_length); - (*motd)[MAX_MOTD_LENGTH - 1] = '\0'; + (*motd)[motd_length - 1] = '\0'; } config_destroy(&cfg); From 77d2ad373aa3fe3472a22e483a2ad6bed7e3fe5f Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sun, 18 May 2014 16:07:26 -0400 Subject: [PATCH 105/117] Fixed IP_Port packed struct being 1 byte too big on windows. --- toxcore/network.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/toxcore/network.h b/toxcore/network.h index f907b9b5..c9fb4637 100644 --- a/toxcore/network.h +++ b/toxcore/network.h @@ -185,10 +185,12 @@ typedef struct __attribute__ ((__packed__)) } IP; -typedef struct __attribute__ ((__packed__)) IP_Port { +typedef struct __attribute__ ((__packed__)) __attribute__((gcc_struct)) +{ IP ip; uint16_t port; -} IP_Port; +} +IP_Port; #define TOX_ENABLE_IPV6_DEFAULT 1 From 28c5665a08a0e1862d5f4e880a9d094534a5a43c Mon Sep 17 00:00:00 2001 From: stal Date: Sun, 18 May 2014 14:56:35 -0700 Subject: [PATCH 106/117] Fix current_time_monotonic on OS X. clock_gettime doesn't exist there, so throw in some equivalent mach stuff. --- toxcore/network.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/toxcore/network.c b/toxcore/network.c index 0505091d..2ffe067f 100644 --- a/toxcore/network.c +++ b/toxcore/network.c @@ -33,6 +33,12 @@ #include #endif +#ifdef __APPLE__ +#include +#include +#endif + +#include #include "network.h" #include "util.h" @@ -229,6 +235,16 @@ uint64_t current_time_monotonic(void) struct timespec monotime; #if defined(__linux__) clock_gettime(CLOCK_MONOTONIC_RAW, &monotime); +#elif defined(__APPLE__) + clock_serv_t muhclock; + mach_timespec_t machtime; + + host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &muhclock); + clock_get_time(muhclock, &machtime); + mach_port_deallocate(mach_task_self(), muhclock); + + monotime.tv_sec = machtime.tv_sec; + monotime.tv_nsec = machtime.tv_nsec; #else clock_gettime(CLOCK_MONOTONIC, &monotime); #endif From 207e87187d61b02098ae548426f84c6cce515525 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sun, 18 May 2014 18:17:42 -0400 Subject: [PATCH 107/117] libsodium header should only be included when libsodium is used. --- toxcore/network.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/toxcore/network.c b/toxcore/network.c index 2ffe067f..4b71d70b 100644 --- a/toxcore/network.c +++ b/toxcore/network.c @@ -38,7 +38,6 @@ #include #endif -#include #include "network.h" #include "util.h" @@ -546,6 +545,11 @@ int networking_wait_cleanup(Networking_Core *net, uint8_t *data) return 1; } +#ifndef VANILLA_NACL +/* Used for sodium_init() */ +#include +#endif + uint8_t at_startup_ran = 0; int networking_at_startup(void) { From 8b5e3d520825f3376ec0fd00ba3aadc60c625d5f Mon Sep 17 00:00:00 2001 From: Maxim Biro Date: Sun, 18 May 2014 19:26:36 -0400 Subject: [PATCH 108/117] Allow multiple instances of the daemon --- other/bootstrap_daemon/tox_bootstrap_daemon.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/other/bootstrap_daemon/tox_bootstrap_daemon.c b/other/bootstrap_daemon/tox_bootstrap_daemon.c index 2c8f7014..0d18d411 100644 --- a/other/bootstrap_daemon/tox_bootstrap_daemon.c +++ b/other/bootstrap_daemon/tox_bootstrap_daemon.c @@ -485,8 +485,7 @@ int main(int argc, char *argv[]) // Check if the PID file exists if (fopen(pid_file_path, "r")) { - syslog(LOG_ERR, "Another instance of the daemon is already running, PID file %s exists. Exiting.\n", pid_file_path); - return 1; + syslog(LOG_ERR, "Another instance of the daemon is already running, PID file %s exists.\n", pid_file_path); } IP ip; @@ -555,10 +554,10 @@ int main(int argc, char *argv[]) print_public_key(dht->self_public_key); // Write the PID file - FILE *pidf = fopen(pid_file_path, "w"); + FILE *pidf = fopen(pid_file_path, "a+"); if (pidf == NULL) { - syslog(LOG_ERR, "Can't open the PID file for writing: %s. Exiting.\n", pid_file_path); + syslog(LOG_ERR, "Couldn't open the PID file for writing: %s. Exiting.\n", pid_file_path); return 1; } @@ -575,7 +574,7 @@ int main(int argc, char *argv[]) } if (pid > 0) { - fprintf(pidf, "%d\n", pid); + fprintf(pidf, "%d ", pid); fclose(pidf); syslog(LOG_DEBUG, "Forked successfully: PID: %d.\n", pid); return 0; From 261a70353ff316cc993c23faf07cb0f60e2e5819 Mon Sep 17 00:00:00 2001 From: Maxim Biro Date: Sun, 18 May 2014 19:28:18 -0400 Subject: [PATCH 109/117] Fixed a bug --- other/bootstrap_daemon/tox_bootstrap_daemon.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/other/bootstrap_daemon/tox_bootstrap_daemon.c b/other/bootstrap_daemon/tox_bootstrap_daemon.c index 0d18d411..afe2b2ac 100644 --- a/other/bootstrap_daemon/tox_bootstrap_daemon.c +++ b/other/bootstrap_daemon/tox_bootstrap_daemon.c @@ -164,8 +164,8 @@ void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_ports, int } (*tcp_relay_ports)[*tcp_relay_port_count] = config_setting_get_int(elem); - if ((*tcp_relay_ports)[i] < MIN_ALLOWED_PORT || (*tcp_relay_ports)[i] > MAX_ALLOWED_PORT) { - syslog(LOG_WARNING, "Port #%d: Invalid port: %u, should be in [%d, %d]. Skipping.\n", i, (*tcp_relay_ports)[i], MIN_ALLOWED_PORT, MAX_ALLOWED_PORT); + if ((*tcp_relay_ports)[*tcp_relay_port_count] < MIN_ALLOWED_PORT || (*tcp_relay_ports)[*tcp_relay_port_count] > MAX_ALLOWED_PORT) { + syslog(LOG_WARNING, "Port #%d: Invalid port: %u, should be in [%d, %d]. Skipping.\n", i, (*tcp_relay_ports)[*tcp_relay_port_count], MIN_ALLOWED_PORT, MAX_ALLOWED_PORT); continue; } @@ -173,7 +173,7 @@ void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_ports, int } // the loop above skips invalid ports, so we adjust the allocated memory size - *tcp_relay_ports = realloc(*tcp_relay_ports, *tcp_relay_port_count * sizeof(uint16_t)); + *tcp_relay_ports = realloc(*tcp_relay_ports, (*tcp_relay_port_count) * sizeof(uint16_t)); } // Gets general config options From fe1694fa6963ca0eceb898e4a07c60c123f23184 Mon Sep 17 00:00:00 2001 From: Maxim Biro Date: Sun, 18 May 2014 19:31:50 -0400 Subject: [PATCH 110/117] Added default ports to the .c file, included 33445 port --- other/bootstrap_daemon/conf | 4 +- other/bootstrap_daemon/tox_bootstrap_daemon.c | 45 +++++++++++++++---- 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/other/bootstrap_daemon/conf b/other/bootstrap_daemon/conf index bbdf7652..23580d9d 100644 --- a/other/bootstrap_daemon/conf +++ b/other/bootstrap_daemon/conf @@ -22,9 +22,9 @@ enable_lan_discovery = true enable_tcp_relay = true -// Tox uses 443 and 3389 ports by default, so it's highly recommended to keep +// Tox uses 443, 3389 and 33445 ports by default, so it's highly recommended to keep // them. -tcp_relay_ports = [443, 3389] +tcp_relay_ports = [443, 3389, 33445] // It's planned to use message of the day as a convenient method of checking // whether a node is up or not, though there are other methods of doing that. diff --git a/other/bootstrap_daemon/tox_bootstrap_daemon.c b/other/bootstrap_daemon/tox_bootstrap_daemon.c index afe2b2ac..66271288 100644 --- a/other/bootstrap_daemon/tox_bootstrap_daemon.c +++ b/other/bootstrap_daemon/tox_bootstrap_daemon.c @@ -58,14 +58,16 @@ #define SLEEP_TIME_MILLISECONDS 30 #define sleep usleep(1000*SLEEP_TIME_MILLISECONDS) -#define DEFAULT_PID_FILE_PATH ".tox_bootstrap_daemon.pid" -#define DEFAULT_KEYS_FILE_PATH ".tox_bootstrap_daemon.keys" -#define DEFAULT_PORT 33445 -#define DEFAULT_ENABLE_IPV6 0 // 1 - true, 0 - false -#define DEFAULT_ENABLE_LAN_DISCOVERY 1 // 1 - true, 0 - false -#define DEFAULT_ENABLE_TCP_RELAY 1 // 1 - true, 0 - false -#define DEFAULT_ENABLE_MOTD 1 // 1 - true, 0 - false -#define DEFAULT_MOTD DAEMON_NAME +#define DEFAULT_PID_FILE_PATH ".tox_bootstrap_daemon.pid" +#define DEFAULT_KEYS_FILE_PATH ".tox_bootstrap_daemon.keys" +#define DEFAULT_PORT 33445 +#define DEFAULT_ENABLE_IPV6 0 // 1 - true, 0 - false +#define DEFAULT_ENABLE_LAN_DISCOVERY 1 // 1 - true, 0 - false +#define DEFAULT_ENABLE_TCP_RELAY 1 // 1 - true, 0 - false +#define DEFAULT_TCP_RELAY_PORTS 443, 3389, 33445 // comma-separated list of ports. make sure to adjust DEFAULT_TCP_RELAY_PORTS_COUNT accordingly +#define DEFAULT_TCP_RELAY_PORTS_COUNT 3 +#define DEFAULT_ENABLE_MOTD 1 // 1 - true, 0 - false +#define DEFAULT_MOTD DAEMON_NAME #define MIN_ALLOWED_PORT 1 #define MAX_ALLOWED_PORT 65535 @@ -129,6 +131,33 @@ void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_ports, int if (ports_array == NULL) { syslog(LOG_WARNING, "No '%s' setting in the configuration file.\n", NAME_TCP_RELAY_PORTS); + syslog(LOG_WARNING, "Using default '%s':\n", NAME_TCP_RELAY_PORTS); + + uint16_t default_ports[DEFAULT_TCP_RELAY_PORTS_COUNT] = {DEFAULT_TCP_RELAY_PORTS}; + + int i; + + for (i = 0; i < DEFAULT_TCP_RELAY_PORTS_COUNT; i ++) { + syslog(LOG_WARNING, "Port #%d: %u\n", i, default_ports[i]); + } + + // similar procedure to the one of reading config file below + *tcp_relay_ports = malloc(DEFAULT_TCP_RELAY_PORTS_COUNT * sizeof(uint16_t)); + + for (i = 0; i < DEFAULT_TCP_RELAY_PORTS_COUNT; i ++) { + + (*tcp_relay_ports)[*tcp_relay_port_count] = default_ports[i]; + if ((*tcp_relay_ports)[*tcp_relay_port_count] < MIN_ALLOWED_PORT || (*tcp_relay_ports)[*tcp_relay_port_count] > MAX_ALLOWED_PORT) { + syslog(LOG_WARNING, "Port #%d: Invalid port: %u, should be in [%d, %d]. Skipping.\n", i, (*tcp_relay_ports)[*tcp_relay_port_count], MIN_ALLOWED_PORT, MAX_ALLOWED_PORT); + continue; + } + + (*tcp_relay_port_count) ++; + } + + // the loop above skips invalid ports, so we adjust the allocated memory size + *tcp_relay_ports = realloc(*tcp_relay_ports, (*tcp_relay_port_count) * sizeof(uint16_t)); + return; } From 286d8d966166c590b2a775b05a7ee7be0f69fe70 Mon Sep 17 00:00:00 2001 From: Maxim Biro Date: Sun, 18 May 2014 19:38:45 -0400 Subject: [PATCH 111/117] Made config file more consistent with default values --- other/bootstrap_daemon/conf | 4 ++-- other/bootstrap_daemon/tox_bootstrap_daemon.c | 2 +- other/bootstrap_daemon/tox_bootstrap_daemon.sh | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/other/bootstrap_daemon/conf b/other/bootstrap_daemon/conf index 23580d9d..c05beff1 100644 --- a/other/bootstrap_daemon/conf +++ b/other/bootstrap_daemon/conf @@ -6,13 +6,13 @@ port = 33445 // A key file is like a password, so keep it where no one can read it. // The daemon should have permission to read/write to it. // Remember to replace the provided example with your own path. -keys_file_path = "/home/tom/.tox_bootstrap_daemon/keys" +keys_file_path = "/home/tom/.tox_bootstrap_daemon/.tox_bootstrap_daemon.keys" // The PID file written to by daemon. // Make sure that the user who runs the daemon has permissions to write to the // PID file. // Remember to replace the provided example with your own path. -pid_file_path = "/home/tom/.tox_bootstrap_daemon/pid" +pid_file_path = "/home/tom/.tox_bootstrap_daemon/.tox_bootstrap_daemon.pid" // Enable IPv6. enable_ipv6 = false diff --git a/other/bootstrap_daemon/tox_bootstrap_daemon.c b/other/bootstrap_daemon/tox_bootstrap_daemon.c index 66271288..ceb4fded 100644 --- a/other/bootstrap_daemon/tox_bootstrap_daemon.c +++ b/other/bootstrap_daemon/tox_bootstrap_daemon.c @@ -53,7 +53,7 @@ #define DAEMON_NAME "tox_bootstrap_daemon" -#define DAEMON_VERSION_NUMBER 2014051700UL // yyyymmmddvv format: yyyy year, mm month, dd day, vv version change count for that day +#define DAEMON_VERSION_NUMBER 2014051800UL // yyyymmmddvv format: yyyy year, mm month, dd day, vv version change count for that day #define SLEEP_TIME_MILLISECONDS 30 #define sleep usleep(1000*SLEEP_TIME_MILLISECONDS) diff --git a/other/bootstrap_daemon/tox_bootstrap_daemon.sh b/other/bootstrap_daemon/tox_bootstrap_daemon.sh index e083ea0b..787498ec 100644 --- a/other/bootstrap_daemon/tox_bootstrap_daemon.sh +++ b/other/bootstrap_daemon/tox_bootstrap_daemon.sh @@ -18,7 +18,7 @@ USER=tom CFG=/home/$USER/.$NAME/conf DAEMON=/home/$USER/.$NAME/$NAME DAEMON_ARGS="$CFG" -PIDFILE=/home/$USER/.$NAME/pid +PIDFILE=/home/$USER/.$NAME/."$NAME".pid SCRIPTNAME=/etc/init.d/$NAME # Exit if the package is not installed From 0d711afbeca8b229d4161b2a07901ace51663c02 Mon Sep 17 00:00:00 2001 From: notsecure Date: Mon, 19 May 2014 09:18:04 -0400 Subject: [PATCH 112/117] IP_Port packing unpacking in onion.c --- toxcore/network.c | 25 +++++++++++++ toxcore/network.h | 15 +++++++- toxcore/onion.c | 91 ++++++++++++++++++++++++----------------------- toxcore/onion.h | 8 ++--- 4 files changed, 90 insertions(+), 49 deletions(-) diff --git a/toxcore/network.c b/toxcore/network.c index 4b71d70b..63d0c3d7 100644 --- a/toxcore/network.c +++ b/toxcore/network.c @@ -891,6 +891,31 @@ void ipport_copy(IP_Port *target, IP_Port *source) memcpy(target, source, sizeof(IP_Port)); }; +/* packing and unpacking functions */ +void ip_pack(uint8_t *data, IP *source) +{ + data[0] = source->family; + memcpy(data + 1, &source->ip6, SIZE_IP6); +} + +void ip_unpack(IP *target, uint8_t *data) +{ + target->family = data[0]; + memcpy(&target->ip6, data + 1, SIZE_IP6); +} + +void ipport_pack(uint8_t *data, IP_Port *source) +{ + ip_pack(data, &source.ip); + memcpy(data + SIZE_IP, &source->port, SIZE_PORT); +} + +void ipport_unpack(IP_Port *target, uint8_t *data) +{ + ip_unpack(&target.ip, data); + memcpy(&target->port, data + SIZE_IP, SIZE_PORT); +} + /* ip_ntoa * converts ip into a string * uses a static buffer, so mustn't used multiple times in the same output diff --git a/toxcore/network.h b/toxcore/network.h index c9fb4637..ffd3d6db 100644 --- a/toxcore/network.h +++ b/toxcore/network.h @@ -89,7 +89,7 @@ typedef int sock_t; #endif #if defined(__sun__) -#define __EXTENSIONS__ 1 // SunOS! +#define __EXTENSIONS__ 1 // SunOS! #if defined(__SunOS5_6__) || defined(__SunOS5_7__) || defined(__SunOS5_8__) || defined(__SunOS5_9__) || defined(__SunOS5_10__) //Nothing needed #else @@ -192,6 +192,13 @@ typedef struct __attribute__ ((__packed__)) __attribute__((gcc_struct)) } IP_Port; + +#define SIZE_IP4 4 +#define SIZE_IP6 16 +#define SIZE_IP (1 + SIZEOF_IP6) +#define SIZE_PORT 2 +#define SIZE_IPPORT (SIZE_IP + SIZE_PORT) + #define TOX_ENABLE_IPV6_DEFAULT 1 /* ip_ntoa @@ -229,6 +236,12 @@ void ip_copy(IP *target, IP *source); /* copies an ip_port structure */ void ipport_copy(IP_Port *target, IP_Port *source); + +void ip_pack(uint8_t *data, IP *source); +void ip_unpack(IP *target, uint8_t *data); +void ipport_pack(uint8_t *data, IP_Port *source); +void ipport_unpack(IP_Port *target, uint8_t *data); + /* * addr_resolve(): * uses getaddrinfo to resolve an address into an IP address diff --git a/toxcore/onion.c b/toxcore/onion.c index 8cc851c2..067b3907 100644 --- a/toxcore/onion.c +++ b/toxcore/onion.c @@ -98,31 +98,32 @@ int send_onion_packet(Networking_Core *net, Onion_Path *path, IP_Port dest, uint return -1; to_net_family(&dest.ip); - uint8_t step1[sizeof(IP_Port) + length]; + uint8_t step1[SIZE_IPPORT + length]; - memcpy(step1, &dest, sizeof(IP_Port)); - memcpy(step1 + sizeof(IP_Port), data, length); + + ipport_pack(step1, &dest); + memcpy(step1 + SIZE_IPPORT, data, length); uint8_t nonce[crypto_box_NONCEBYTES]; random_nonce(nonce); - uint8_t step2[sizeof(IP_Port) + SEND_BASE + length]; - memcpy(step2, &path->ip_port3, sizeof(IP_Port)); - memcpy(step2 + sizeof(IP_Port), path->public_key3, crypto_box_PUBLICKEYBYTES); + uint8_t step2[SIZE_IPPORT + SEND_BASE + length]; + ipport_pack(step2, &path->ip_port3); + memcpy(step2 + SIZE_IPPORT, path->public_key3, crypto_box_PUBLICKEYBYTES); int len = encrypt_data_symmetric(path->shared_key3, nonce, step1, sizeof(step1), - step2 + sizeof(IP_Port) + crypto_box_PUBLICKEYBYTES); + step2 + SIZE_IPPORT + crypto_box_PUBLICKEYBYTES); - if ((uint32_t)len != sizeof(IP_Port) + length + crypto_box_MACBYTES) + if ((uint32_t)len != SIZE_IPPORT + length + crypto_box_MACBYTES) return -1; - uint8_t step3[sizeof(IP_Port) + SEND_BASE * 2 + length]; - memcpy(step3, &path->ip_port2, sizeof(IP_Port)); - memcpy(step3 + sizeof(IP_Port), path->public_key2, crypto_box_PUBLICKEYBYTES); + uint8_t step3[SIZE_IPPORT + SEND_BASE * 2 + length]; + ipport_pack(step3, &path->ip_port2); + memcpy(step3 + SIZE_IPPORT, path->public_key2, crypto_box_PUBLICKEYBYTES); len = encrypt_data_symmetric(path->shared_key2, nonce, step2, sizeof(step2), - step3 + sizeof(IP_Port) + crypto_box_PUBLICKEYBYTES); + step3 + SIZE_IPPORT + crypto_box_PUBLICKEYBYTES); - if ((uint32_t)len != sizeof(IP_Port) + SEND_BASE + length + crypto_box_MACBYTES) + if ((uint32_t)len != SIZE_IPPORT + SEND_BASE + length + crypto_box_MACBYTES) return -1; uint8_t packet[1 + length + SEND_1]; @@ -133,7 +134,7 @@ int send_onion_packet(Networking_Core *net, Onion_Path *path, IP_Port dest, uint len = encrypt_data_symmetric(path->shared_key1, nonce, step3, sizeof(step3), packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES); - if ((uint32_t)len != sizeof(IP_Port) + SEND_BASE * 2 + length + crypto_box_MACBYTES) + if ((uint32_t)len != SIZE_IPPORT + SEND_BASE * 2 + length + crypto_box_MACBYTES) return -1; if ((uint32_t)sendpacket(net, path->ip_port1, packet, sizeof(packet)) != sizeof(packet)) @@ -191,20 +192,20 @@ static int handle_send_initial(void *object, IP_Port source, uint8_t *packet, ui int onion_send_1(Onion *onion, uint8_t *plain, uint32_t len, IP_Port source, uint8_t *nonce) { IP_Port send_to; - memcpy(&send_to, plain, sizeof(IP_Port)); + ipport_unpack(&send_to, plain); to_host_family(&send_to.ip); uint8_t data[ONION_MAX_PACKET_SIZE]; data[0] = NET_PACKET_ONION_SEND_1; memcpy(data + 1, nonce, crypto_box_NONCEBYTES); - memcpy(data + 1 + crypto_box_NONCEBYTES, plain + sizeof(IP_Port), len - sizeof(IP_Port)); - uint32_t data_len = 1 + crypto_box_NONCEBYTES + (len - sizeof(IP_Port)); + memcpy(data + 1 + crypto_box_NONCEBYTES, plain + SIZE_IPPORT, len - SIZE_IPPORT); + uint32_t data_len = 1 + crypto_box_NONCEBYTES + (len - SIZE_IPPORT); uint8_t *ret_part = data + data_len; new_nonce(ret_part); - len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, (uint8_t *)&source, sizeof(IP_Port), + len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, (uint8_t *)&source, SIZE_IPPORT, ret_part + crypto_box_NONCEBYTES); - if (len != sizeof(IP_Port) + crypto_box_MACBYTES) + if (len != SIZE_IPPORT + crypto_box_MACBYTES) return 1; data_len += crypto_box_NONCEBYTES + len; @@ -237,19 +238,19 @@ static int handle_send_1(void *object, IP_Port source, uint8_t *packet, uint32_t return 1; IP_Port send_to; - memcpy(&send_to, plain, sizeof(IP_Port)); + ipport_unpack(&send_to, plain); to_host_family(&send_to.ip); uint8_t data[ONION_MAX_PACKET_SIZE]; data[0] = NET_PACKET_ONION_SEND_2; memcpy(data + 1, packet + 1, crypto_box_NONCEBYTES); - memcpy(data + 1 + crypto_box_NONCEBYTES, plain + sizeof(IP_Port), len - sizeof(IP_Port)); - uint32_t data_len = 1 + crypto_box_NONCEBYTES + (len - sizeof(IP_Port)); + memcpy(data + 1 + crypto_box_NONCEBYTES, plain + SIZE_IPPORT, len - SIZE_IPPORT); + uint32_t data_len = 1 + crypto_box_NONCEBYTES + (len - SIZE_IPPORT); uint8_t *ret_part = data + data_len; new_nonce(ret_part); - uint8_t ret_data[RETURN_1 + sizeof(IP_Port)]; - memcpy(ret_data, &source, sizeof(IP_Port)); - memcpy(ret_data + sizeof(IP_Port), packet + (length - RETURN_1), RETURN_1); + uint8_t ret_data[RETURN_1 + SIZE_IPPORT]; + ipport_pack(ret_data, &source); + memcpy(ret_data + SIZE_IPPORT, packet + (length - RETURN_1), RETURN_1); len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data), ret_part + crypto_box_NONCEBYTES); @@ -286,17 +287,17 @@ static int handle_send_2(void *object, IP_Port source, uint8_t *packet, uint32_t return 1; IP_Port send_to; - memcpy(&send_to, plain, sizeof(IP_Port)); + ipport_unpack(&send_to, plain); to_host_family(&send_to.ip); uint8_t data[ONION_MAX_PACKET_SIZE]; - memcpy(data, plain + sizeof(IP_Port), len - sizeof(IP_Port)); - uint32_t data_len = (len - sizeof(IP_Port)); - uint8_t *ret_part = data + (len - sizeof(IP_Port)); + memcpy(data, plain + SIZE_IPPORT, len - SIZE_IPPORT); + uint32_t data_len = (len - SIZE_IPPORT); + uint8_t *ret_part = data + (len - SIZE_IPPORT); new_nonce(ret_part); - uint8_t ret_data[RETURN_2 + sizeof(IP_Port)]; - memcpy(ret_data, &source, sizeof(IP_Port)); - memcpy(ret_data + sizeof(IP_Port), packet + (length - RETURN_2), RETURN_2); + uint8_t ret_data[RETURN_2 + SIZE_IPPORT]; + ipport_pack(ret_data, &source); + memcpy(ret_data + SIZE_IPPORT, packet + (length - RETURN_2), RETURN_2); len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data), ret_part + crypto_box_NONCEBYTES); @@ -324,19 +325,19 @@ static int handle_recv_3(void *object, IP_Port source, uint8_t *packet, uint32_t change_symmetric_key(onion); - uint8_t plain[sizeof(IP_Port) + RETURN_2]; + uint8_t plain[SIZE_IPPORT + RETURN_2]; int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES, - sizeof(IP_Port) + RETURN_2 + crypto_box_MACBYTES, plain); + SIZE_IPPORT + RETURN_2 + crypto_box_MACBYTES, plain); if ((uint32_t)len != sizeof(plain)) return 1; IP_Port send_to; - memcpy(&send_to, plain, sizeof(IP_Port)); + ipport_unpack(&send_to, plain); uint8_t data[ONION_MAX_PACKET_SIZE]; data[0] = NET_PACKET_ONION_RECV_2; - memcpy(data + 1, plain + sizeof(IP_Port), RETURN_2); + memcpy(data + 1, plain + SIZE_IPPORT, RETURN_2); memcpy(data + 1 + RETURN_2, packet + 1 + RETURN_3, length - (1 + RETURN_3)); uint32_t data_len = 1 + RETURN_2 + (length - (1 + RETURN_3)); @@ -358,19 +359,19 @@ static int handle_recv_2(void *object, IP_Port source, uint8_t *packet, uint32_t change_symmetric_key(onion); - uint8_t plain[sizeof(IP_Port) + RETURN_1]; + uint8_t plain[SIZE_IPPORT + RETURN_1]; int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES, - sizeof(IP_Port) + RETURN_1 + crypto_box_MACBYTES, plain); + SIZE_IPPORT + RETURN_1 + crypto_box_MACBYTES, plain); if ((uint32_t)len != sizeof(plain)) return 1; IP_Port send_to; - memcpy(&send_to, plain, sizeof(IP_Port)); + ipport_unpack(&send_to, plain); uint8_t data[ONION_MAX_PACKET_SIZE]; data[0] = NET_PACKET_ONION_RECV_1; - memcpy(data + 1, plain + sizeof(IP_Port), RETURN_1); + memcpy(data + 1, plain + SIZE_IPPORT, RETURN_1); memcpy(data + 1 + RETURN_1, packet + 1 + RETURN_2, length - (1 + RETURN_2)); uint32_t data_len = 1 + RETURN_1 + (length - (1 + RETURN_2)); @@ -392,14 +393,16 @@ static int handle_recv_1(void *object, IP_Port source, uint8_t *packet, uint32_t change_symmetric_key(onion); - IP_Port send_to; - + uint8_t plain[SIZE_IPPORT]; int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES, - sizeof(IP_Port) + crypto_box_MACBYTES, (uint8_t *) &send_to); + SIZE_IPPORT + crypto_box_MACBYTES, plain); - if ((uint32_t)len != sizeof(IP_Port)) + if ((uint32_t)len != SIZE_IPPORT) return 1; + IP_Port send_to; + ipport_unpack(&send_to, plain); + uint32_t data_len = length - (1 + RETURN_1); if (onion->recv_1_function && send_to.ip.family != AF_INET && send_to.ip.family != AF_INET6) diff --git a/toxcore/onion.h b/toxcore/onion.h index 712bbf13..13dc8f52 100644 --- a/toxcore/onion.h +++ b/toxcore/onion.h @@ -41,11 +41,11 @@ typedef struct { #define ONION_MAX_PACKET_SIZE 1400 -#define ONION_RETURN_1 (crypto_box_NONCEBYTES + sizeof(IP_Port) + crypto_box_MACBYTES) -#define ONION_RETURN_2 (crypto_box_NONCEBYTES + sizeof(IP_Port) + crypto_box_MACBYTES + ONION_RETURN_1) -#define ONION_RETURN_3 (crypto_box_NONCEBYTES + sizeof(IP_Port) + crypto_box_MACBYTES + ONION_RETURN_2) +#define ONION_RETURN_1 (crypto_box_NONCEBYTES + SIZE_IPPORT + crypto_box_MACBYTES) +#define ONION_RETURN_2 (crypto_box_NONCEBYTES + SIZE_IPPORT + crypto_box_MACBYTES + ONION_RETURN_1) +#define ONION_RETURN_3 (crypto_box_NONCEBYTES + SIZE_IPPORT + crypto_box_MACBYTES + ONION_RETURN_2) -#define ONION_SEND_BASE (crypto_box_PUBLICKEYBYTES + sizeof(IP_Port) + crypto_box_MACBYTES) +#define ONION_SEND_BASE (crypto_box_PUBLICKEYBYTES + SIZE_IPPORT + crypto_box_MACBYTES) #define ONION_SEND_3 (crypto_box_NONCEBYTES + ONION_SEND_BASE + ONION_RETURN_2) #define ONION_SEND_2 (crypto_box_NONCEBYTES + ONION_SEND_BASE*2 + ONION_RETURN_1) #define ONION_SEND_1 (crypto_box_NONCEBYTES + ONION_SEND_BASE*3) From 116f3d46e89ce2741b6823707a2d60cd70b093c9 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Mon, 19 May 2014 10:57:56 -0400 Subject: [PATCH 113/117] Removed now useless code. --- toxcore/onion_client.c | 11 +---------- toxcore/onion_client.h | 8 -------- 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index 03ffbaa7..dfdb1638 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c @@ -334,7 +334,6 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, Node_format *n Onion_Node *list_nodes = NULL; uint8_t *reference_id = NULL; - uint32_t *ping_nodes_sent_second = NULL; Last_Pinged *last_pinged = NULL; uint8_t *last_pinged_index = NULL; @@ -342,13 +341,11 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, Node_format *n if (num == 0) { list_nodes = onion_c->clients_announce_list; reference_id = onion_c->c->self_public_key; - ping_nodes_sent_second = &onion_c->ping_nodes_sent_second; last_pinged = onion_c->last_pinged; last_pinged_index = &onion_c->last_pinged_index; } else { list_nodes = onion_c->friends_list[num - 1].clients_list; reference_id = onion_c->friends_list[num - 1].real_client_id; - ping_nodes_sent_second = &onion_c->friends_list[num - 1].ping_nodes_sent_second; last_pinged = onion_c->friends_list[num - 1].last_pinged; last_pinged_index = &onion_c->friends_list[num - 1].last_pinged_index; } @@ -358,9 +355,6 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, Node_format *n for (i = 0; i < num_nodes; ++i) { - if (*ping_nodes_sent_second > MAX_PING_NODES_SECOND_PEER) - return 0; - if (!lan_ips_accepted) if (LAN_ip(nodes[i].ip_port.ip) == 0) continue; @@ -375,8 +369,7 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, Node_format *n } if (j == MAX_ONION_CLIENTS && good_to_ping(last_pinged, last_pinged_index, nodes[i].client_id)) { - if (client_send_announce_request(onion_c, num, nodes[i].ip_port, nodes[i].client_id, NULL, ~0) == 0) - ++*ping_nodes_sent_second; + client_send_announce_request(onion_c, num, nodes[i].ip_port, nodes[i].client_id, NULL, ~0); } } } @@ -1073,10 +1066,8 @@ void do_onion_client(Onion_Client *onion_c) for (i = 0; i < onion_c->num_friends; ++i) { do_friend(onion_c, i); cleanup_friend(onion_c, i); - onion_c->friends_list[i].ping_nodes_sent_second = 0; } - onion_c->ping_nodes_sent_second = 0; onion_c->last_run = unix_time(); } diff --git a/toxcore/onion_client.h b/toxcore/onion_client.h index 0d2e84a5..9cf6cf3e 100644 --- a/toxcore/onion_client.h +++ b/toxcore/onion_client.h @@ -44,11 +44,6 @@ #define ONION_PATH_TIMEOUT 30 #define ONION_PATH_MAX_LIFETIME 600 -/* A cheap way of making it take less bandwidth at startup: - by limiting the number of ping packets we can send per - second per peer. */ -#define MAX_PING_NODES_SECOND_PEER 5 - #define MAX_STORED_PINGED_NODES 9 #define MIN_NODE_PING_TIME 10 @@ -98,7 +93,6 @@ typedef struct { uint64_t last_seen; Onion_Client_Paths onion_paths; - uint32_t ping_nodes_sent_second; Last_Pinged last_pinged[MAX_STORED_PINGED_NODES]; uint8_t last_pinged_index; @@ -127,8 +121,6 @@ typedef struct { uint8_t temp_public_key[crypto_box_PUBLICKEYBYTES]; uint8_t temp_secret_key[crypto_box_SECRETKEYBYTES]; - uint32_t ping_nodes_sent_second; - Last_Pinged last_pinged[MAX_STORED_PINGED_NODES]; Ping_Array announce_ping_array; From cecefd290ac42648356b790e7e214fa24e629cdc Mon Sep 17 00:00:00 2001 From: notsecure Date: Mon, 19 May 2014 11:34:40 -0400 Subject: [PATCH 114/117] mistakes forgot to build before pushing --- toxcore/network.c | 4 ++-- toxcore/network.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/toxcore/network.c b/toxcore/network.c index 63d0c3d7..f1e94996 100644 --- a/toxcore/network.c +++ b/toxcore/network.c @@ -906,13 +906,13 @@ void ip_unpack(IP *target, uint8_t *data) void ipport_pack(uint8_t *data, IP_Port *source) { - ip_pack(data, &source.ip); + ip_pack(data, &source->ip); memcpy(data + SIZE_IP, &source->port, SIZE_PORT); } void ipport_unpack(IP_Port *target, uint8_t *data) { - ip_unpack(&target.ip, data); + ip_unpack(&target->ip, data); memcpy(&target->port, data + SIZE_IP, SIZE_PORT); } diff --git a/toxcore/network.h b/toxcore/network.h index ffd3d6db..09f0df18 100644 --- a/toxcore/network.h +++ b/toxcore/network.h @@ -195,7 +195,7 @@ IP_Port; #define SIZE_IP4 4 #define SIZE_IP6 16 -#define SIZE_IP (1 + SIZEOF_IP6) +#define SIZE_IP (1 + SIZE_IP6) #define SIZE_PORT 2 #define SIZE_IPPORT (SIZE_IP + SIZE_PORT) From ede8455a5a3a6f3b68a676ecbdda6f5561e7d464 Mon Sep 17 00:00:00 2001 From: notsecure Date: Mon, 19 May 2014 11:56:45 -0400 Subject: [PATCH 115/117] function comments in header --- toxcore/network.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/toxcore/network.h b/toxcore/network.h index 09f0df18..0eb7bbd0 100644 --- a/toxcore/network.h +++ b/toxcore/network.h @@ -237,9 +237,13 @@ void ip_copy(IP *target, IP *source); void ipport_copy(IP_Port *target, IP_Port *source); +/* packs IP into data, writes SIZE_IP bytes to data */ void ip_pack(uint8_t *data, IP *source); +/* unpacks IP from data, reads SIZE_IP bytes from data */ void ip_unpack(IP *target, uint8_t *data); +/* packs IP_Port into data, writes SIZE_IPPORT bytes to data */ void ipport_pack(uint8_t *data, IP_Port *source); +/* unpacks IP_Port from data, reads SIZE_IPPORT bytes to data */ void ipport_unpack(IP_Port *target, uint8_t *data); /* From e85feb8a3db42a0285b940a090c60102fae50374 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Mon, 19 May 2014 12:56:36 -0400 Subject: [PATCH 116/117] Fixed a bug where someone could just send back the ping request packet with only the first byte set to 1 instead of 0 and the public key set to the one of the reciever as a valid response packet. This breaks network compatibility with all previous cores. --- docs/updates/DHT.md | 2 +- toxcore/ping.c | 45 ++++++++++++++++++++++++++++++++------------- 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/docs/updates/DHT.md b/docs/updates/DHT.md index ba6abe3a..17db70ce 100644 --- a/docs/updates/DHT.md +++ b/docs/updates/DHT.md @@ -87,7 +87,7 @@ Valid queries and Responses: Ping(Request and response): ``` -[byte with value: 00 for request, 01 for response][char array (client node_id), length=32 bytes][random 24 byte nonce][Encrypted with the nonce and private key of the sender: [random 8 byte (ping_id)]] +[byte with value: 00 for request, 01 for response][char array (client node_id), length=32 bytes][random 24 byte nonce][Encrypted with the nonce and private key of the sender: [1 byte type (0 for request, 1 for response)][random 8 byte (ping_id)]] ``` ping_id = a random integer, the response must contain the exact same number as the request diff --git a/toxcore/ping.c b/toxcore/ping.c index 2d16e354..c01170ab 100644 --- a/toxcore/ping.c +++ b/toxcore/ping.c @@ -54,7 +54,8 @@ struct PING { }; -#define DHT_PING_SIZE (1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(uint64_t) + crypto_box_MACBYTES) +#define PING_PLAIN_SIZE (1 + sizeof(uint64_t)) +#define DHT_PING_SIZE (1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + PING_PLAIN_SIZE + crypto_box_MACBYTES) #define PING_DATA_SIZE (CLIENT_ID_SIZE + sizeof(IP_Port)) int send_ping_request(PING *ping, IP_Port ipp, uint8_t *client_id) @@ -79,6 +80,10 @@ int send_ping_request(PING *ping, IP_Port ipp, uint8_t *client_id) if (ping_id == 0) return 1; + uint8_t ping_plain[PING_PLAIN_SIZE]; + ping_plain[0] = NET_PACKET_PING_REQUEST; + memcpy(ping_plain + 1, &ping_id, sizeof(ping_id)); + pk[0] = NET_PACKET_PING_REQUEST; id_copy(pk + 1, ping->dht->self_public_key); // Our pubkey new_nonce(pk + 1 + CLIENT_ID_SIZE); // Generate new nonce @@ -86,10 +91,10 @@ int send_ping_request(PING *ping, IP_Port ipp, uint8_t *client_id) rc = encrypt_data_symmetric(shared_key, pk + 1 + CLIENT_ID_SIZE, - (uint8_t *) &ping_id, sizeof(ping_id), + ping_plain, sizeof(ping_plain), pk + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES); - if (rc != sizeof(ping_id) + crypto_box_MACBYTES) + if (rc != PING_PLAIN_SIZE + crypto_box_MACBYTES) return 1; return sendpacket(ping->dht->net, ipp, pk, sizeof(pk)); @@ -104,6 +109,10 @@ static int send_ping_response(PING *ping, IP_Port ipp, uint8_t *client_id, uint6 if (id_equal(client_id, ping->dht->self_public_key)) return 1; + uint8_t ping_plain[PING_PLAIN_SIZE]; + ping_plain[0] = NET_PACKET_PING_RESPONSE; + memcpy(ping_plain + 1, &ping_id, sizeof(ping_id)); + pk[0] = NET_PACKET_PING_RESPONSE; id_copy(pk + 1, ping->dht->self_public_key); // Our pubkey new_nonce(pk + 1 + CLIENT_ID_SIZE); // Generate new nonce @@ -111,10 +120,10 @@ static int send_ping_response(PING *ping, IP_Port ipp, uint8_t *client_id, uint6 // Encrypt ping_id using recipient privkey rc = encrypt_data_symmetric(shared_encryption_key, pk + 1 + CLIENT_ID_SIZE, - (uint8_t *) &ping_id, sizeof(ping_id), + ping_plain, sizeof(ping_plain), pk + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES ); - if (rc != sizeof(ping_id) + crypto_box_MACBYTES) + if (rc != PING_PLAIN_SIZE + crypto_box_MACBYTES) return 1; return sendpacket(ping->dht->net, ipp, pk, sizeof(pk)); @@ -124,7 +133,6 @@ static int handle_ping_request(void *_dht, IP_Port source, uint8_t *packet, uint { DHT *dht = _dht; int rc; - uint64_t ping_id; if (length != DHT_PING_SIZE) return 1; @@ -136,17 +144,23 @@ static int handle_ping_request(void *_dht, IP_Port source, uint8_t *packet, uint uint8_t shared_key[crypto_box_BEFORENMBYTES]; + uint8_t ping_plain[PING_PLAIN_SIZE]; // Decrypt ping_id DHT_get_shared_key_recv(dht, shared_key, packet + 1); rc = decrypt_data_symmetric(shared_key, packet + 1 + CLIENT_ID_SIZE, packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, - sizeof(ping_id) + crypto_box_MACBYTES, - (uint8_t *) &ping_id ); + PING_PLAIN_SIZE + crypto_box_MACBYTES, + ping_plain ); - if (rc != sizeof(ping_id)) + if (rc != sizeof(ping_plain)) return 1; + if (ping_plain[0] != NET_PACKET_PING_REQUEST) + return 1; + + uint64_t ping_id; + memcpy(&ping_id, ping_plain + 1, sizeof(ping_id)); // Send response send_ping_response(ping, source, packet + 1, ping_id, shared_key); add_to_ping(ping, packet + 1, source); @@ -158,7 +172,6 @@ static int handle_ping_response(void *_dht, IP_Port source, uint8_t *packet, uin { DHT *dht = _dht; int rc; - uint64_t ping_id; if (length != DHT_PING_SIZE) return 1; @@ -173,16 +186,22 @@ static int handle_ping_response(void *_dht, IP_Port source, uint8_t *packet, uin // generate key to encrypt ping_id with recipient privkey DHT_get_shared_key_sent(ping->dht, shared_key, packet + 1); + uint8_t ping_plain[PING_PLAIN_SIZE]; // Decrypt ping_id rc = decrypt_data_symmetric(shared_key, packet + 1 + CLIENT_ID_SIZE, packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, - sizeof(ping_id) + crypto_box_MACBYTES, - (uint8_t *) &ping_id); + PING_PLAIN_SIZE + crypto_box_MACBYTES, + ping_plain); - if (rc != sizeof(ping_id)) + if (rc != sizeof(ping_plain)) return 1; + if (ping_plain[0] != NET_PACKET_PING_RESPONSE) + return 1; + + uint64_t ping_id; + memcpy(&ping_id, ping_plain + 1, sizeof(ping_id)); uint8_t data[PING_DATA_SIZE]; if (ping_array_check(data, sizeof(data), &ping->ping_array, ping_id) != sizeof(data)) From d27a83820c6af2f0d6d813b9916d324e9ae3d137 Mon Sep 17 00:00:00 2001 From: notsecure Date: Mon, 19 May 2014 14:18:26 -0400 Subject: [PATCH 117/117] added missing ipport_pack --- toxcore/onion.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/toxcore/onion.c b/toxcore/onion.c index 067b3907..479c6209 100644 --- a/toxcore/onion.c +++ b/toxcore/onion.c @@ -195,6 +195,9 @@ int onion_send_1(Onion *onion, uint8_t *plain, uint32_t len, IP_Port source, uin ipport_unpack(&send_to, plain); to_host_family(&send_to.ip); + uint8_t ip_port[SIZE_IPPORT]; + ipport_pack(ip_port, &source); + uint8_t data[ONION_MAX_PACKET_SIZE]; data[0] = NET_PACKET_ONION_SEND_1; memcpy(data + 1, nonce, crypto_box_NONCEBYTES); @@ -202,7 +205,7 @@ int onion_send_1(Onion *onion, uint8_t *plain, uint32_t len, IP_Port source, uin uint32_t data_len = 1 + crypto_box_NONCEBYTES + (len - SIZE_IPPORT); uint8_t *ret_part = data + data_len; new_nonce(ret_part); - len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, (uint8_t *)&source, SIZE_IPPORT, + len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ip_port, SIZE_IPPORT, ret_part + crypto_box_NONCEBYTES); if (len != SIZE_IPPORT + crypto_box_MACBYTES)