mirror of
https://github.com/irungentoo/toxcore.git
synced 2024-03-22 13:30:51 +08:00
Merge upstream fo real now?
This commit is contained in:
commit
c9f1c6882d
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
@ -291,6 +291,76 @@ 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 (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++;
|
||||
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, 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, 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;
|
||||
|
||||
if (data[0] == 1 && data[1] == 2 && data[2] == 3 && data[3] == 4 && data[4] == 5) {
|
||||
data_callback_good++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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();
|
||||
|
@ -320,6 +390,71 @@ 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);
|
||||
|
||||
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 *)conn) + 2);
|
||||
routing_status_handler(conn, status_callback, (void *)2);
|
||||
routing_data_handler(conn, data_callback, (void *)3);
|
||||
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);
|
||||
c_sleep(50);
|
||||
do_TCP_server(tcp_s);
|
||||
c_sleep(50);
|
||||
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);
|
||||
do_TCP_server(tcp_s);
|
||||
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");
|
||||
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);
|
||||
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");
|
||||
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
|
||||
|
||||
|
|
|
@ -9,12 +9,6 @@
|
|||
#include <check.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#ifndef VANILLA_NACL
|
||||
#include <sodium.h>
|
||||
#else
|
||||
#include <crypto_box.h>
|
||||
#define crypto_box_MACBYTES (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES)
|
||||
#endif
|
||||
|
||||
void rand_bytes(uint8_t *b, size_t blen)
|
||||
{
|
||||
|
@ -126,12 +120,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 +180,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 +191,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");
|
||||
|
@ -215,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;
|
||||
|
@ -233,13 +227,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");
|
||||
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_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 +242,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];
|
||||
|
@ -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); \
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
#include "../testing/misc_tools.c" // hex_string_to_bin
|
||||
#include "../toxcore/Messenger.h"
|
||||
#include "../toxcore/Lossless_UDP.h"
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
@ -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
|
||||
|
@ -299,27 +298,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 +309,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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
@ -176,26 +176,30 @@ 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->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, s);
|
||||
ck_assert_msg(ret == 0, "Failed to create/send onion announce_request packet.");
|
||||
handled_test_3 = 0;
|
||||
|
||||
while (handled_test_3 == 0) {
|
||||
do_onion(onion1);
|
||||
do_onion(onion2);
|
||||
c_sleep(50);
|
||||
}
|
||||
|
||||
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->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, s);
|
||||
|
||||
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);
|
||||
|
@ -203,12 +207,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;
|
||||
|
@ -233,10 +237,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;
|
||||
|
@ -297,8 +301,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;
|
||||
|
||||
|
|
|
@ -96,21 +96,26 @@ 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)
|
||||
{
|
||||
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 +136,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 +147,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"));
|
||||
|
@ -227,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);
|
||||
|
@ -241,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;
|
||||
}
|
||||
|
@ -284,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);
|
||||
|
||||
|
@ -331,7 +345,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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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]]
|
||||
[uint8_t message[messagelen]]
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -135,11 +139,16 @@ 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.
|
||||
|
||||
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.
|
||||
|
|
118
docs/Tox_middle_level_network_protocol.txt
Normal file
118
docs/Tox_middle_level_network_protocol.txt
Normal file
|
@ -0,0 +1,118 @@
|
|||
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:
|
||||
|
||||
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)][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.
|
||||
|
||||
cookie response packet:
|
||||
[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.
|
||||
|
||||
The Cookie should be basically:
|
||||
[nonce][encrypted data:[uint64_t time][Senders real public key (32
|
||||
bytes)][Senders dht 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)][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 receiver 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, 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 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 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:[plain data]]
|
||||
|
||||
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)
|
||||
2: connection kill packet (lossy packet) (tells the other that the connection is over)
|
||||
...
|
||||
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.
|
||||
|
||||
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -79,18 +79,15 @@ 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:
|
||||
|
||||
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
|
||||
|
||||
|
@ -98,16 +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 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:[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]]
|
||||
```
|
||||
|
|
|
@ -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
|
||||
# --------------------------------------------------------------
|
||||
|
|
|
@ -3,16 +3,16 @@
|
|||
// 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"
|
||||
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
|
||||
|
@ -20,6 +20,18 @@ enable_ipv6 = false
|
|||
// Automatically bootstrap with nodes on local area network.
|
||||
enable_lan_discovery = true
|
||||
|
||||
enable_tcp_relay = true
|
||||
|
||||
// Tox uses 443, 3389 and 33445 ports by default, so it's highly recommended to keep
|
||||
// them.
|
||||
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.
|
||||
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.
|
||||
|
@ -28,8 +40,8 @@ enable_lan_discovery = true
|
|||
// 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"
|
||||
|
|
|
@ -21,37 +21,56 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
// system provided
|
||||
#include <arpa/inet.h>
|
||||
#include <syslog.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// C
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <libconfig.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <string.h>
|
||||
|
||||
// 3rd party
|
||||
#include <libconfig.h>
|
||||
|
||||
// ./configure
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "../../toxcore/DHT.h"
|
||||
#include "../../toxcore/friend_requests.h"
|
||||
// toxcore
|
||||
#include "../../toxcore/LAN_discovery.h"
|
||||
#include "../../toxcore/onion_announce.h"
|
||||
#include "../../toxcore/TCP_server.h"
|
||||
#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 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)
|
||||
|
||||
#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_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
|
||||
|
||||
|
||||
// Uses the already existing key or creates one if it didn't exist
|
||||
|
@ -75,11 +94,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,22 +112,111 @@ 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;
|
||||
}
|
||||
|
||||
// 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);
|
||||
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;
|
||||
}
|
||||
|
||||
if (config_setting_is_array(ports_array) == CONFIG_FALSE) {
|
||||
syslog(LOG_WARNING, "'%s' setting should be an array. Array syntax: 'setting = [value1, value2, ...]'.\n", NAME_TCP_RELAY_PORTS);
|
||||
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)[*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));
|
||||
}
|
||||
|
||||
// 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`
|
||||
// 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_lan_discovery, int *enable_tcp_relay, uint16_t **tcp_relay_ports, int *tcp_relay_port_count,
|
||||
int *enable_motd, char **motd)
|
||||
{
|
||||
config_t cfg;
|
||||
|
||||
|
@ -116,6 +225,9 @@ 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";
|
||||
const char *NAME_ENABLE_MOTD = "enable_motd";
|
||||
const char *NAME_MOTD = "motd";
|
||||
|
||||
config_init(&cfg);
|
||||
|
||||
|
@ -172,6 +284,44 @@ 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;
|
||||
}
|
||||
|
||||
// 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)[motd_length - 1] = '\0';
|
||||
}
|
||||
|
||||
config_destroy(&cfg);
|
||||
|
||||
syslog(LOG_DEBUG, "Successfully read:\n");
|
||||
|
@ -181,6 +331,25 @@ int get_general_config(char *cfg_file_path, char **pid_file_path, char **keys_fi
|
|||
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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -255,15 +424,14 @@ 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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
@ -280,9 +448,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++;
|
||||
}
|
||||
|
@ -296,17 +464,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);
|
||||
|
@ -318,6 +482,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;
|
||||
|
@ -328,30 +494,33 @@ 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;
|
||||
int enable_motd;
|
||||
char *motd;
|
||||
|
||||
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, &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);
|
||||
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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
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");
|
||||
|
@ -366,31 +535,58 @@ int main(int argc, char *argv[])
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (enable_lan_discovery) {
|
||||
LANdiscovery_init(dht);
|
||||
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;
|
||||
}
|
||||
|
||||
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_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;
|
||||
}
|
||||
|
||||
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");
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -407,7 +603,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;
|
||||
|
@ -438,6 +634,11 @@ int main(int argc, char *argv[])
|
|||
|
||||
int waiting_for_dht_connection = 1;
|
||||
|
||||
if (enable_lan_discovery) {
|
||||
LANdiscovery_init(dht);
|
||||
syslog(LOG_DEBUG, "Initialized LAN discovery.\n");
|
||||
}
|
||||
|
||||
while (1) {
|
||||
do_DHT(dht);
|
||||
|
||||
|
@ -446,6 +647,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)) {
|
||||
|
|
|
@ -11,14 +11,14 @@
|
|||
|
||||
# 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
|
||||
PIDFILE=/home/$USER/.$NAME/."$NAME".pid
|
||||
SCRIPTNAME=/etc/init.d/$NAME
|
||||
|
||||
# Exit if the package is not installed
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,5 +34,4 @@ libtoxav_la_LIBADD = libtoxcore.la \
|
|||
$(PTHREAD_LIBS) \
|
||||
$(AV_LIBS)
|
||||
|
||||
|
||||
endif
|
57
toxav/msi.c
57
toxav/msi.c
|
@ -207,7 +207,22 @@ static inline__ const uint8_t *stringify_response ( MSIResponse response )
|
|||
}
|
||||
|
||||
|
||||
<<<<<<< HEAD
|
||||
|
||||
=======
|
||||
#define ON_HEADER(iterator, header, descriptor, size_const) \
|
||||
( memcmp(iterator, descriptor, size_const) == 0){ /* Okay */ \
|
||||
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 | \
|
||||
(uint16_t) *(iterator + 1); \
|
||||
header.header_value = calloc(sizeof(uint8_t), _value_size); \
|
||||
header.size = _value_size; \
|
||||
memcpy(header.header_value, iterator + 2, _value_size);\
|
||||
iterator = iterator + 2 + _value_size; /* set iterator at new header or end_byte */ \
|
||||
}
|
||||
>>>>>>> upstream/master
|
||||
|
||||
/**
|
||||
* @brief Parse raw 'data' received from socket into MSIMessage struct.
|
||||
|
@ -1085,11 +1100,11 @@ int handle_recv_start ( MSISession *session, MSICall* call, MSIMessage *msg )
|
|||
|
||||
call->state = call_active;
|
||||
|
||||
call->key_peer = calloc ( sizeof ( uint8_t ), crypto_secretbox_KEYBYTES );
|
||||
memcpy ( call->key_peer, msg->cryptokey.header_value, crypto_secretbox_KEYBYTES );
|
||||
call->key_peer = calloc ( sizeof ( uint8_t ), crypto_box_KEYBYTES );
|
||||
memcpy ( call->key_peer, msg->cryptokey.header_value, crypto_box_KEYBYTES );
|
||||
|
||||
call->nonce_peer = calloc ( sizeof ( uint8_t ), crypto_secretbox_NONCEBYTES );
|
||||
memcpy ( call->nonce_peer, msg->nonce.header_value, crypto_secretbox_NONCEBYTES );
|
||||
call->nonce_peer = calloc ( sizeof ( uint8_t ), crypto_box_NONCEBYTES );
|
||||
memcpy ( call->nonce_peer, msg->nonce.header_value, crypto_box_NONCEBYTES );
|
||||
|
||||
flush_peer_type ( call, msg, 0 );
|
||||
|
||||
|
@ -1183,6 +1198,7 @@ int handle_recv_starting ( MSISession *session, MSICall* call, MSIMessage *msg )
|
|||
}
|
||||
|
||||
/* Generate local key/nonce to send */
|
||||
<<<<<<< HEAD
|
||||
call->key_local = calloc ( sizeof ( uint8_t ), crypto_secretbox_KEYBYTES );
|
||||
new_symmetric_key ( call->key_local );
|
||||
|
||||
|
@ -1195,13 +1211,33 @@ int handle_recv_starting ( MSISession *session, MSICall* call, MSIMessage *msg )
|
|||
|
||||
call->nonce_peer = calloc ( sizeof ( uint8_t ), crypto_secretbox_NONCEBYTES );
|
||||
memcpy ( call->nonce_peer, msg->nonce.header_value, crypto_secretbox_NONCEBYTES );
|
||||
=======
|
||||
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_box_NONCEBYTES );
|
||||
new_nonce ( session->call->nonce_local );
|
||||
|
||||
/* Save peer key/nonce */
|
||||
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_box_NONCEBYTES );
|
||||
memcpy ( session->call->nonce_peer, msg->nonce.header_value, crypto_box_NONCEBYTES );
|
||||
>>>>>>> upstream/master
|
||||
|
||||
call->state = call_active;
|
||||
|
||||
MSIMessage *_msg_start = msi_new_message ( TYPE_REQUEST, stringify_request ( start ) );
|
||||
<<<<<<< HEAD
|
||||
msi_msg_set_cryptokey ( _msg_start, call->key_local, crypto_secretbox_KEYBYTES );
|
||||
msi_msg_set_nonce ( _msg_start, call->nonce_local, crypto_secretbox_NONCEBYTES );
|
||||
send_message ( session, call, _msg_start, msg->friend_id );
|
||||
=======
|
||||
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 );
|
||||
>>>>>>> upstream/master
|
||||
free_message ( _msg_start );
|
||||
|
||||
flush_peer_type ( call, msg, 0 );
|
||||
|
@ -1593,6 +1629,7 @@ int msi_answer ( MSISession* session, int32_t call_index, MSICallType call_type
|
|||
|
||||
/* Now set the local encryption key and pass it with STARTING message */
|
||||
|
||||
<<<<<<< HEAD
|
||||
session->calls[call_index]->key_local = calloc ( sizeof ( uint8_t ), crypto_secretbox_KEYBYTES );
|
||||
new_symmetric_key ( session->calls[call_index]->key_local );
|
||||
|
||||
|
@ -1601,6 +1638,16 @@ int msi_answer ( MSISession* session, int32_t call_index, MSICallType call_type
|
|||
|
||||
msi_msg_set_cryptokey ( _msg_starting, session->calls[call_index]->key_local, crypto_secretbox_KEYBYTES );
|
||||
msi_msg_set_nonce ( _msg_starting, session->calls[call_index]->nonce_local, crypto_secretbox_NONCEBYTES );
|
||||
=======
|
||||
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_box_NONCEBYTES );
|
||||
new_nonce ( session->call->nonce_local );
|
||||
|
||||
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 );
|
||||
>>>>>>> upstream/master
|
||||
|
||||
send_message ( session, session->calls[call_index], _msg_starting, session->calls[call_index]->peers[session->calls[call_index]->peer_count - 1] );
|
||||
free_message ( _msg_starting );
|
||||
|
@ -1689,4 +1736,4 @@ int msi_stopcall ( MSISession* session, int32_t call_index )
|
|||
terminate_call ( session, session->calls[call_index] );
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
11
toxav/msi.h
11
toxav/msi.h
|
@ -72,21 +72,22 @@ typedef struct _MSICall { /* Call info structure */
|
|||
|
||||
uint8_t id[CALL_ID_LEN]; /* Random value identifying the call */
|
||||
|
||||
uint8_t *key_local; /* The key for encryption */
|
||||
uint8_t *key_peer; /* The key for decryption */
|
||||
uint8_t *key_local; /* The key for encryption */
|
||||
uint8_t *key_peer; /* The key for decryption */
|
||||
|
||||
uint8_t *nonce_local; /* Local nonce */
|
||||
uint8_t *nonce_peer; /* Peer nonce */
|
||||
uint8_t *nonce_local; /* Local nonce */
|
||||
uint8_t *nonce_peer; /* Peer nonce */
|
||||
|
||||
int ringing_tout_ms; /* Ringing timeout in ms */
|
||||
|
||||
int request_timer_id; /* Timer id for outgoing request/action */
|
||||
int ringing_timer_id; /* Timer id for ringing timeout */
|
||||
|
||||
|
||||
pthread_mutex_t mutex; /* It's to be assumed that call will have
|
||||
* separate thread so add mutex
|
||||
*/
|
||||
uint32_t *peers;
|
||||
uint32_t *peers;
|
||||
uint16_t peer_count;
|
||||
|
||||
int32_t call_idx; /* Index of this call in MSISession */
|
||||
|
|
1460
toxav/phone.c
Executable file
1460
toxav/phone.c
Executable file
File diff suppressed because it is too large
Load Diff
|
@ -2048,6 +2048,7 @@ static int handle_packet(void *object, int i, uint8_t *temp, uint16_t len)
|
|||
if (m->friend_action)
|
||||
(*m->friend_action)(m, i, action_terminated, action_length, m->friend_action_userdata);
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2207,7 +2208,7 @@ void do_friends(Messenger *m)
|
|||
m->friendlist[i].friendrequest_lastsent = temp_time;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (m->friendlist[i].status == FRIEND_REQUESTED
|
||||
|| m->friendlist[i].status == FRIEND_CONFIRMED) { /* friend is not online. */
|
||||
if (m->friendlist[i].status == FRIEND_REQUESTED) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user