Example #1
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.
 *
 * return -1 on failure.
 * return 0 on success.
 */
int onion_set_friend_DHT_pubkey(Onion_Client *onion_c, int friend_num, const 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].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);

    return 0;
}
Example #2
0
/* Callback for dht public key changes. */
static void dht_pk_callback(void *object, int32_t number, const uint8_t *dht_public_key)
{
    Friend_Connections *fr_c = object;
    Friend_Conn *friend_con = get_conn(fr_c, number);

    if (!friend_con)
        return;

    friend_con->dht_ping_lastrecv = unix_time();

    if (memcmp(friend_con->dht_temp_pk, dht_public_key, crypto_box_PUBLICKEYBYTES) == 0)
        return;

    if (friend_con->dht_lock) {
        if (DHT_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock) != 0) {
            printf("a. Could not delete dht peer. Please report this.\n");
            return;
        }

        friend_con->dht_lock = 0;
    }

    DHT_addfriend(fr_c->dht, dht_public_key, dht_ip_callback, object, number, &friend_con->dht_lock);

    if (friend_con->crypt_connection_id == -1) {
        friend_new_connection(fr_c, number);
    }

    set_connection_dht_public_key(fr_c->net_crypto, friend_con->crypt_connection_id, dht_public_key);
    onion_set_friend_DHT_pubkey(fr_c->onion_c, friend_con->onion_friendnum, dht_public_key);

    memcpy(friend_con->dht_temp_pk, dht_public_key, crypto_box_PUBLICKEYBYTES);
}
static int handle_fakeid_announce(void *object, uint8_t *source_pubkey, uint8_t *data, uint32_t length)
{
    Onion_Client *onion_c = object;

    if (length < FAKEID_DATA_MIN_LENGTH)
        return 1;

    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)
        return 1;

    uint64_t no_replay;
    net_to_host(data + 1, sizeof(no_replay));
    memcpy(&no_replay, data + 1, sizeof(uint64_t));

    if (no_replay <= onion_c->friends_list[friend_num].last_noreplay)
        return 1;

    onion_c->friends_list[friend_num].last_noreplay = no_replay;

    if (memcmp(data + 1 + sizeof(uint64_t), onion_c->friends_list[friend_num].fake_client_id,
               crypto_box_PUBLICKEYBYTES) != 0) {
        DHT_delfriend(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id);

        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;
        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;

    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);
    }

    return 0;
}
static void cleanup_friend(Onion_Client *onion_c, uint16_t friendnum)
{
    if (friendnum >= onion_c->num_friends)
        return;

    if (onion_c->friends_list[friendnum].status == 0)
        return;

    if (onion_c->friends_list[friendnum].is_fake_clientid && !onion_c->friends_list[friendnum].is_online
            && is_timeout(onion_c->friends_list[friendnum].last_seen, DEAD_ONION_TIMEOUT)) {
        onion_c->friends_list[friendnum].is_fake_clientid = 0;
        DHT_delfriend(onion_c->dht, onion_c->friends_list[friendnum].fake_client_id);
    }
}
Example #5
0
/* main friend_connections loop. */
void do_friend_connections(Friend_Connections *fr_c, void *userdata)
{
    const uint64_t temp_time = unix_time();

    for (uint32_t i = 0; i < fr_c->num_cons; ++i) {
        Friend_Conn *const friend_con = get_conn(fr_c, i);

        if (friend_con) {
            if (friend_con->status == FRIENDCONN_STATUS_CONNECTING) {
                if (friend_con->dht_pk_lastrecv + FRIEND_DHT_TIMEOUT < temp_time) {
                    if (friend_con->dht_lock) {
                        DHT_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock);
                        friend_con->dht_lock = 0;
                        memset(friend_con->dht_temp_pk, 0, CRYPTO_PUBLIC_KEY_SIZE);
                    }
                }

                if (friend_con->dht_ip_port_lastrecv + FRIEND_DHT_TIMEOUT < temp_time) {
                    friend_con->dht_ip_port.ip.family = 0;
                }

                if (friend_con->dht_lock) {
                    if (friend_new_connection(fr_c, i) == 0) {
                        set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_ip_port, 0);
                        connect_to_saved_tcp_relays(fr_c, i, (MAX_FRIEND_TCP_CONNECTIONS / 2)); /* Only fill it half up. */
                    }
                }
            } else if (friend_con->status == FRIENDCONN_STATUS_CONNECTED) {
                if (friend_con->ping_lastsent + FRIEND_PING_INTERVAL < temp_time) {
                    send_ping(fr_c, i);
                }

                if (friend_con->share_relays_lastsent + SHARE_RELAYS_INTERVAL < temp_time) {
                    send_relays(fr_c, i);
                }

                if (friend_con->ping_lastrecv + FRIEND_CONNECTION_TIMEOUT < temp_time) {
                    /* If we stopped receiving ping packets, kill it. */
                    crypto_kill(fr_c->net_crypto, friend_con->crypt_connection_id);
                    friend_con->crypt_connection_id = -1;
                    handle_status(fr_c, i, 0, userdata); /* Going offline. */
                }
            }
        }
    }

    if (fr_c->local_discovery_enabled) {
        LANdiscovery(fr_c);
    }
}
Example #6
0
/* remove a friend
   return 0 if success
   return -1 if failure */
int m_delfriend(int friendnumber)
{
    if (friendnumber >= numfriends || friendnumber < 0)
        return -1;

    DHT_delfriend(friendlist[friendnumber].client_id);
    crypto_kill(friendlist[friendnumber].crypt_connection_id);
    free(friendlist[friendnumber].userstatus);
    memset(&friendlist[friendnumber], 0, sizeof(Friend));
    uint32_t i;
    for (i = numfriends; i != 0; --i) {
        if (friendlist[i].status != 0)
            break;
    }
    numfriends = i;
    return 0;
}
Example #7
0
/* main friend_connections loop. */
void do_friend_connections(Friend_Connections *fr_c)
{
    uint32_t i;
    uint64_t temp_time = unix_time();

    for (i = 0; i < fr_c->num_cons; ++i) {
        Friend_Conn *friend_con = get_conn(fr_c, i);

        if (friend_con) {
            if (friend_con->status == FRIENDCONN_STATUS_CONNECTING) {
                if (friend_con->dht_ping_lastrecv + FRIEND_DHT_TIMEOUT < temp_time) {
                    if (friend_con->dht_lock) {
                        DHT_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock);
                        friend_con->dht_lock = 0;
                    }
                }

                if (friend_con->dht_ip_port_lastrecv + FRIEND_DHT_TIMEOUT < temp_time) {
                    friend_con->dht_ip_port.ip.family = 0;
                }

                if (friend_con->dht_lock) {
                    if (friend_new_connection(fr_c, i) == 0) {
                        set_connection_dht_public_key(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_temp_pk);
                        set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_ip_port);
                    }
                }

            } else if (friend_con->status == FRIENDCONN_STATUS_CONNECTED) {
                if (friend_con->ping_lastsent + FRIEND_PING_INTERVAL < temp_time) {
                    send_ping(fr_c, i);
                }

                if (friend_con->ping_lastrecv + FRIEND_CONNECTION_TIMEOUT < temp_time) {
                    /* If we stopped receiving ping packets, kill it. */
                    crypto_kill(fr_c->net_crypto, friend_con->crypt_connection_id);
                    friend_con->crypt_connection_id = -1;
                    handle_status(fr_c, i, 0); /* Going offline. */
                }
            }
        }
    }
}
Example #8
0
/* remove a friend
   return 0 if success
   return -1 if failure */
int m_delfriend(int friendnumber)
{
    if (friendnumber >= numfriends || friendnumber < 0)
        return -1;

    DHT_delfriend(friendlist[friendnumber].client_id);
    crypto_kill(friendlist[friendnumber].crypt_connection_id);
    free(friendlist[friendnumber].statusmessage);
    memset(&friendlist[friendnumber], 0, sizeof(Friend));
    uint32_t i;

    for (i = numfriends; i != 0; --i) {
        if (friendlist[i-1].status != NOFRIEND)
            break;
    }
    numfriends = i;
    realloc_friendlist(numfriends + 1);

    return 0;
}
/* Kill a friend connection.
 *
 * return -1 on failure.
 * return 0 on success.
 */
int kill_friend_connection(Friend_Connections *fr_c, int friendcon_id)
{
    Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);

    if (!friend_con)
        return -1;

    if (friend_con->lock_count) {
        --friend_con->lock_count;
        return 0;
    }

    onion_delfriend(fr_c->onion_c, friend_con->onion_friendnum);
    crypto_kill(fr_c->net_crypto, friend_con->crypt_connection_id);

    if (friend_con->dht_lock) {
        DHT_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock);
    }

    return wipe_friend_conn(fr_c, friendcon_id);
}
Example #10
0
static void change_dht_pk(Friend_Connections *fr_c, int friendcon_id, const uint8_t *dht_public_key)
{
    Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);

    if (!friend_con)
        return;

    friend_con->dht_pk_lastrecv = unix_time();

    if (friend_con->dht_lock) {
        if (DHT_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock) != 0) {
            printf("a. Could not delete dht peer. Please report this.\n");
            return;
        }

        friend_con->dht_lock = 0;
    }

    DHT_addfriend(fr_c->dht, dht_public_key, dht_ip_callback, fr_c, friendcon_id, &friend_con->dht_lock);
    memcpy(friend_con->dht_temp_pk, dht_public_key, crypto_box_PUBLICKEYBYTES);
}
Example #11
0
/* Delete a friend.
 *
 * return -1 on failure.
 * return the deleted friend number on success.
 */
int onion_delfriend(Onion_Client *onion_c, int friend_num)
{
    if ((uint32_t)friend_num >= onion_c->num_friends)
        return -1;

    DHT_delfriend(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id);
    memset(&(onion_c->friends_list[friend_num]), 0, sizeof(Onion_Friend));
    uint32_t i;

    for (i = onion_c->num_friends; i != 0; --i) {
        if (onion_c->friends_list[i].status != 0)
            break;
    }

    if (onion_c->num_friends != i) {
        onion_c->num_friends = i;
        realloc_onion_friends(onion_c, onion_c->num_friends);
    }

    return friend_num;
}
Example #12
0
/* remove a friend
   return 0 if success
   return -1 if failure */
int m_delfriend(Messenger *m, int friendnumber)
{
    if (friendnumber >= m->numfriends || friendnumber < 0)
        return -1;

    DHT_delfriend(m->friendlist[friendnumber].client_id);
    crypto_kill(m->friendlist[friendnumber].crypt_connection_id);
    free(m->friendlist[friendnumber].statusmessage);
    memset(&(m->friendlist[friendnumber]), 0, sizeof(Friend));
    uint32_t i;

    for (i = m->numfriends; i != 0; --i) {
        if (m->friendlist[i - 1].status != NOFRIEND)
            break;
    }

    m->numfriends = i;

    if (realloc_friendlist(m, m->numfriends) != 0)
        return FAERR_NOMEM;

    return 0;
}