Beispiel #1
0
static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_Port dest, const uint8_t *dest_pubkey,
                                        const uint8_t *ping_id, uint32_t pathnum)
{
    if (num > onion_c->num_friends)
        return -1;

    uint64_t sendback;

    if (new_sendback(onion_c, num, dest_pubkey, dest, &sendback) == -1)
        return -1;

    uint8_t zero_ping_id[ONION_PING_ID_SIZE] = {0};

    if (ping_id == NULL)
        ping_id = zero_ping_id;

    Onion_Path path;

    Node_format dest_node;
    dest_node.ip_port = dest;
    memcpy(dest_node.client_id, dest_pubkey, crypto_box_PUBLICKEYBYTES);

    if (num == 0) {
        if (random_path(onion_c->dht, &onion_c->onion_paths, pathnum, &path) == -1)
            return -1;

        uint8_t packet[ONION_MAX_PACKET_SIZE];
        int len = create_announce_request(packet, sizeof(packet), &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);

        if (len == -1) {
            return -1;
        }

        return send_onion_packet_tcp_udp(onion_c, path.ip_port1, packet, len);
    } else {
        if (random_path(onion_c->dht, &onion_c->friends_list[num - 1].onion_paths, pathnum, &path) == -1)
            return -1;

        uint8_t packet[ONION_MAX_PACKET_SIZE];
        int len = create_announce_request(packet, sizeof(packet), &path, dest_node,
                                          onion_c->friends_list[num - 1].temp_public_key, onion_c->friends_list[num - 1].temp_secret_key, ping_id,
                                          onion_c->friends_list[num - 1].real_client_id, zero_ping_id, sendback);

        if (len == -1) {
            return -1;
        }

        return send_onion_packet_tcp_udp(onion_c, path.ip_port1, packet, len);
    }
}
Beispiel #2
0
/* Send data of length length to friendnum.
 * This data will be received by the friend using the Onion_Data_Handlers callbacks.
 *
 * Even if this function succeeds, the friend might not receive any data.
 *
 * return the number of packets sent on success
 * return -1 on failure.
 */
int send_onion_data(const Onion_Client *onion_c, int friend_num, const uint8_t *data, uint32_t length)
{
    if ((uint32_t)friend_num >= onion_c->num_friends)
        return -1;

    if (length + DATA_IN_RESPONSE_MIN_SIZE > MAX_DATA_REQUEST_SIZE)
        return -1;

    if (length == 0)
        return -1;

    uint8_t nonce[crypto_box_NONCEBYTES];
    random_nonce(nonce);

    uint8_t packet[DATA_IN_RESPONSE_MIN_SIZE + length];
    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))
        return -1;

    uint32_t i, good_nodes[MAX_ONION_CLIENTS], num_good = 0, num_nodes = 0;
    Onion_Path path[MAX_ONION_CLIENTS];
    Onion_Node *list_nodes = onion_c->friends_list[friend_num].clients_list;

    for (i = 0; i < MAX_ONION_CLIENTS; ++i) {
        if (is_timeout(list_nodes[i].timestamp, ONION_NODE_TIMEOUT))
            continue;

        ++num_nodes;

        if (list_nodes[i].is_stored) {
            if (random_path(onion_c, &onion_c->friends_list[friend_num].onion_paths, ~0, &path[num_good]) == -1)
                continue;

            good_nodes[num_good] = i;
            ++num_good;
        }
    }

    if (num_good < (num_nodes / 4) + 1)
        return -1;

    uint32_t good = 0;

    for (i = 0; i < num_good; ++i) {
        uint8_t o_packet[ONION_MAX_PACKET_SIZE];
        len = create_data_request(o_packet, sizeof(o_packet), onion_c->friends_list[friend_num].real_client_id,
                                  list_nodes[good_nodes[i]].data_public_key, nonce, packet, sizeof(packet));

        if (len == -1)
            continue;

        if (send_onion_packet_tcp_udp(onion_c, &path[i], list_nodes[good_nodes[i]].ip_port, o_packet, len) == 0)
            ++good;
    }

    return good;
}
Beispiel #3
0
static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_Port dest, uint8_t *dest_pubkey,
                                        uint8_t *ping_id)
{
    if (num > onion_c->num_friends)
        return -1;

    uint8_t sendback[ONION_ANNOUNCE_SENDBACK_DATA_LENGTH];

    if (new_sendback(onion_c, 0, dest_pubkey, dest, sendback) == -1)
        return -1;

    uint8_t zero_ping_id[ONION_PING_ID_SIZE] = {0};

    if (ping_id == NULL)
        ping_id = zero_ping_id;

    Node_format nodes[4];

    if (random_path(onion_c, nodes) == -1)
        return -1;

    nodes[3].ip_port = dest;
    memcpy(nodes[3].client_id, dest_pubkey, crypto_box_PUBLICKEYBYTES);

    if (num == 0) {
        return send_announce_request(onion_c->dht, nodes, onion_c->dht->c->self_public_key,
                                     onion_c->dht->c->self_secret_key, ping_id,
                                     onion_c->dht->c->self_public_key, sendback);
    } else {
        return send_announce_request(onion_c->dht, nodes, onion_c->friends_list[num - 1].temp_public_key,
                                     onion_c->friends_list[num - 1].temp_secret_key, ping_id,
                                     onion_c->friends_list[num - 1].real_client_id, sendback);
    }
}
Beispiel #4
0
static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_Port dest, const uint8_t *dest_pubkey,
                                        const uint8_t *ping_id, uint32_t pathnum)
{
    if (num > onion_c->num_friends)
        return -1;

    uint64_t sendback;
    Onion_Path path;

    if (num == 0) {
        if (random_path(onion_c, &onion_c->onion_paths, pathnum, &path) == -1)
            return -1;
    } else {
        if (random_path(onion_c, &onion_c->friends_list[num - 1].onion_paths, pathnum, &path) == -1)
            return -1;
    }

    if (new_sendback(onion_c, num, dest_pubkey, dest, path.path_num, &sendback) == -1)
        return -1;

    uint8_t zero_ping_id[ONION_PING_ID_SIZE] = {0};

    if (ping_id == NULL)
        ping_id = zero_ping_id;

    uint8_t request[ONION_ANNOUNCE_REQUEST_SIZE];
    int len;

    if (num == 0) {
        len = create_announce_request(request, sizeof(request), dest_pubkey, 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 {
        len = create_announce_request(request, sizeof(request), dest_pubkey, onion_c->friends_list[num - 1].temp_public_key,
                                      onion_c->friends_list[num - 1].temp_secret_key, ping_id, onion_c->friends_list[num - 1].real_client_id, zero_ping_id,
                                      sendback);
    }

    if (len == -1) {
        return -1;
    }

    return send_onion_packet_tcp_udp(onion_c, &path, dest, request, len);
}
/* Send data of length length to friendnum.
 * This data will be recieved by the friend using the Onion_Data_Handlers callbacks.
 *
 * Even if this function succeeds, the friend might not recieve any data.
 *
 * return the number of packets sent on success
 * return -1 on failure.
 */
int send_onion_data(Onion_Client *onion_c, int friend_num, uint8_t *data, uint32_t length)
{
    if ((uint32_t)friend_num >= onion_c->num_friends)
        return -1;

    if (length + DATA_IN_RESPONSE_MIN_SIZE + ONION_DATA_RESPONSE_MIN_SIZE + ONION_SEND_1 > MAX_DATA_SIZE)
        return -1;

    if (length == 0)
        return -1;

    uint8_t nonce[crypto_box_NONCEBYTES];
    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,
                           length, packet + crypto_box_PUBLICKEYBYTES);

    if ((uint32_t)len + crypto_box_PUBLICKEYBYTES != sizeof(packet))
        return -1;

    uint32_t i, good = 0;
    Onion_Node *list_nodes = onion_c->friends_list[friend_num].clients_list;

    for (i = 0; i < MAX_ONION_CLIENTS; ++i) {
        if (is_timeout(list_nodes[i].timestamp, ONION_NODE_TIMEOUT))
            continue;

        if (list_nodes[i].is_stored) {
            Node_format nodes[4];

            Onion_Path path;

            if (random_path(onion_c->dht, &onion_c->friends_list[friend_num].onion_paths, ~0, &path) == -1)
                continue;

            memcpy(nodes[3].client_id, list_nodes[i].client_id, crypto_box_PUBLICKEYBYTES);
            nodes[3].ip_port = list_nodes[i].ip_port;

            if (send_data_request(onion_c->net, &path, list_nodes[i].ip_port, onion_c->friends_list[friend_num].real_client_id,
                                  list_nodes[i].data_public_key, nonce, packet, sizeof(packet)) == 0)
                ++good;
        }
    }

    return good;
}