Beispiel #1
0
/**
 * Sends an ABORT message downstream to clients
 */
void send_downstream_abort(struct pr_group_list_t *group, uint32_t dest_id,
                           const char *message, int current)
{
    unsigned char *buf;
    struct uftp_h *header;
    struct abort_h *abort_hdr;
    int payloadlen;

    buf = safe_calloc(MAXMTU, 1);

    header = (struct uftp_h *)buf;
    abort_hdr = (struct abort_h *)(buf + sizeof(struct uftp_h));

    set_uftp_header(header, ABORT, group);
    header->seq = group->send_seq_down++;
    header->src_id = uid;
    abort_hdr->func = ABORT;
    abort_hdr->hlen = sizeof(struct abort_h) / 4;
    if ((dest_id == 0) && current) {
        abort_hdr->flags |= FLAG_CURRENT_FILE;
    }
    abort_hdr->host = dest_id;
    strncpy(abort_hdr->message, message, sizeof(abort_hdr->message) - 1);
    payloadlen = sizeof(struct uftp_h) + sizeof(struct abort_h);

    // Proxies should never need to send an encrypted ABORT

    if (nb_sendto(listener, buf, payloadlen, 0,
            (struct sockaddr *)&group->privatemcast,
            family_len(group->privatemcast)) == SOCKET_ERROR) {
        gsockerror(group, "Error sending ABORT");
    }

    free(buf);
}
Beispiel #2
0
/**
 * Sends out a data packet.  All headers should be populated except blsize
 */
int send_data(const struct finfo_t *finfo, unsigned char *packet, int datalen,
              unsigned char *encpacket)
{
    struct uftp_h *header;
    struct fileseg_h *fileseg;
    int payloadlen;
    unsigned char *outpacket;

    header = (struct uftp_h *)packet;
    fileseg = (struct fileseg_h *)(packet + sizeof(struct uftp_h));

    payloadlen = sizeof(struct fileseg_h) + datalen;
    if (keytype != KEY_NONE) {
        if (!encrypt_and_sign(packet, &encpacket, payloadlen, mtu, keytype,
                groupkey, groupsalt, ivlen, hashtype, grouphmackey, hmaclen,
                sigtype, privkey, rsalen)) {
            log0(0, 0, "Error encrypting FILESEG");
            return 0;
        }
        outpacket = encpacket;
        payloadlen = ntohs(((struct uftp_h *)outpacket)->blsize);
    } else {
        outpacket = packet;
        header->blsize = htons(payloadlen);
    }

    if (nb_sendto(sock, outpacket, payloadlen + sizeof(struct uftp_h), 0,
               (struct sockaddr *)&receive_dest,
               sizeof(receive_dest)) == SOCKET_ERROR) {
        sockerror(0, 0, "Error sending FILESEG");
        return 0;
    }

    return 1;
}
Beispiel #3
0
/**
 * Sends an HB_RESP in response to an HB_REQ
 */
void send_hb_response(const struct sockaddr_in *src, int response)
{
    unsigned char *packet;
    struct uftp_h *header;
    struct hb_resp_h *hbresp;
    int meslen;

    packet = calloc(sizeof(struct uftp_h) + sizeof(struct hb_resp_h), 1);
    if (packet == NULL) {
        syserror(0, 0, "calloc failed!");
        exit(1);
    }

    header = (struct uftp_h *)packet;
    hbresp = (struct hb_resp_h *)(packet + sizeof(struct uftp_h));
    header->uftp_id = UFTP_VER_NUM;
    header->func = HB_RESP;
    header->blsize = ntohs(sizeof(struct hb_resp_h));
    hbresp->func = HB_RESP;
    hbresp->authenticated = response;
    if (response == HB_AUTH_CHALLENGE) {
        hbresp->nonce = htonl(down_nonce);
    }

    meslen = sizeof(struct uftp_h) + sizeof(struct hb_resp_h);
    if (nb_sendto(listener, packet, meslen, 0, (struct sockaddr *)src,
                  sizeof(struct sockaddr_in)) == SOCKET_ERROR) {
        sockerror(0, 0, "Error sending HB_RESP");
    } else {
        log(0, 0, "Sent HB_RESP to %s:%d", inet_ntoa(src->sin_addr),
                                           ntohs(src->sin_port));
    }
    free(packet);
}
Beispiel #4
0
/**
 * Sends a KEYINFO_ACK in response to a KEYINFO
 */
void send_keyinfo_ack(struct group_list_t *group)
{
    unsigned char *buf, *encrypted;
    struct uftp_h *header;
    struct keyinfoack_h *keyinfo_ack;
    unsigned char *verifydata, *verify_hash, *verify_val;
    unsigned int payloadlen, hashlen;
    int verifylen, enclen, len;

    buf = safe_calloc(MAXMTU, 1);

    header = (struct uftp_h *)buf;
    keyinfo_ack = (struct keyinfoack_h *)(buf + sizeof(struct uftp_h));

    set_uftp_header(header, KEYINFO_ACK, group);
    keyinfo_ack->func = KEYINFO_ACK;
    keyinfo_ack->hlen = sizeof(struct keyinfoack_h) / 4;

    verifydata = build_verify_data(group, &verifylen);
    if (!verifydata) {
        glog0(group, "Error getting verify data");
        send_abort(group, "Error getting verify data");
        free(buf);
        return;
    }

    verify_hash = safe_calloc(group->hmaclen, 1);
    verify_val = safe_calloc(VERIFY_LEN + group->hmaclen, 1);
    hash(group->hashtype, verifydata, verifylen, verify_hash, &hashlen);
    PRF(group->hashtype, VERIFY_LEN, group->groupmaster,
            sizeof(group->groupmaster), "client finished",
            verify_hash, hashlen, verify_val, &len);
    memcpy(keyinfo_ack->verify_data, verify_val, VERIFY_LEN);
    free(verifydata);
    free(verify_hash);
    free(verify_val);

    payloadlen = sizeof(struct keyinfoack_h);
    encrypted = NULL;
    if (!encrypt_and_sign(buf, &encrypted, payloadlen, &enclen, group->keytype,
            group->groupkey, group->groupsalt, &group->ivctr, group->ivlen,
            group->hashtype, group->grouphmackey, group->hmaclen,group->sigtype,
            group->keyextype, group->client_privkey,group->client_privkeylen)) {
        glog0(group, "Error encrypting KEYINFO_ACK");
        free(buf);
        return;
    }
    payloadlen = enclen + sizeof(struct uftp_h);

    if (nb_sendto(listener, encrypted, payloadlen, 0,
               (struct sockaddr *)&(group->replyaddr),
               family_len(group->replyaddr)) == SOCKET_ERROR) {
        gsockerror(group, "Error sending KEYINFO_ACK");
    } else {
        glog2(group, "KEYINFO_ACK sent");
    }
    free(encrypted);
    free(buf);
}
Beispiel #5
0
/**
 * Sends back a CC_ACK message for congestion control feedback
 */
void send_cc_ack(struct group_list_t *group)
{
    unsigned char *buf, *encrypted, *outpacket;
    struct uftp_h *header;
    struct cc_ack_h *cc_ack;
    struct tfmcc_ack_info_he *tfmcc;
    int payloadlen, enclen;

    buf = safe_calloc(MAXMTU, 1);

    header = (struct uftp_h *)buf;
    cc_ack = (struct cc_ack_h *)(buf + sizeof(struct uftp_h));
    tfmcc = (struct tfmcc_ack_info_he *)((unsigned char *)cc_ack +
                sizeof(struct cc_ack_h));

    set_uftp_header(header, CC_ACK, group);
    cc_ack->func = CC_ACK;
    cc_ack->hlen =
            (sizeof(struct cc_ack_h) + sizeof(struct tfmcc_ack_info_he)) / 4;
    set_tfmcc_ack_info(group, tfmcc);

    payloadlen = cc_ack->hlen * 4;
    if ((group->phase != PHASE_REGISTERED) && (group->keytype != KEY_NONE)) {
        encrypted = NULL;
        if (!encrypt_and_sign(buf, &encrypted, payloadlen, &enclen,
                group->keytype, group->groupkey, group->groupsalt,&group->ivctr,
                group->ivlen, group->hashtype, group->grouphmackey,
                group->hmaclen, group->sigtype, group->keyextype,
                group->client_privkey, group->client_privkeylen)) {
            glog0(group, "Error encrypting CC_ACK");
            free(buf);
            return;
        }
        outpacket = encrypted;
        payloadlen = enclen;
    } else {
        encrypted = NULL;
        outpacket = buf;
    }
    payloadlen += sizeof(struct uftp_h);

    if (nb_sendto(listener, outpacket, payloadlen, 0,
               (struct sockaddr *)&group->replyaddr,
               family_len(group->replyaddr)) == SOCKET_ERROR) {
        gsockerror(group, "Error sending CC_ACK");
    } else {
        glog2(group, "CC_ACK sent");
    }
    set_timeout(group, 0);
    group->cc_time.tv_sec = 0;
    group->cc_time.tv_usec = 0;
    free(buf);
}
Beispiel #6
0
/**
 * Sends an ABORT message to a server
 */
void send_abort(struct group_list_t *group, const char *message)
{
    unsigned char *buf, *encrypted, *outpacket;
    struct uftp_h *header;
    struct abort_h *abort_hdr;
    int payloadlen, enclen;

    buf = safe_calloc(MAXMTU, 1);

    header = (struct uftp_h *)buf;
    abort_hdr = (struct abort_h *)(buf + sizeof(struct uftp_h));

    set_uftp_header(header, ABORT, group);
    abort_hdr->func = ABORT;
    abort_hdr->hlen = sizeof(struct abort_h) / 4;
    abort_hdr->host = 0;
    strncpy(abort_hdr->message, message, sizeof(abort_hdr->message) - 1);

    payloadlen = sizeof(struct abort_h);
    if ((group->phase != PHASE_REGISTERED) &&
            (group->keytype != KEY_NONE)) {
        encrypted = NULL;
        if (!encrypt_and_sign(buf, &encrypted, payloadlen, &enclen,
                group->keytype, group->groupkey, group->groupsalt,&group->ivctr,
                group->ivlen, group->hashtype, group->grouphmackey,
                group->hmaclen, group->sigtype, group->keyextype,
                group->client_privkey, group->client_privkeylen)) {
            glog0(group, "Error encrypting ABORT");
            free(buf);
            return;
        }
        outpacket = encrypted;
        payloadlen = enclen;
    } else {
        encrypted = NULL;
        outpacket = buf;
    }
    payloadlen += sizeof(struct uftp_h);

    if (nb_sendto(listener, outpacket, payloadlen, 0,
               (struct sockaddr *)&group->replyaddr,
               family_len(group->replyaddr)) == SOCKET_ERROR) {
        gsockerror(group, "Error sending ABORT");
    }

    flush_disk_cache(group);
    file_cleanup(group, 1);
    free(buf);
    free(encrypted);
}
Beispiel #7
0
/**
 * Sends an ABORT message to one or more clients
 */
void send_abort(const struct finfo_t *finfo, const char *message,
                const struct sockaddr_in *destaddr,
                const struct in_addr *dest, int encrypt)
{
    unsigned char *buf, *encrypted, *outpacket;
    struct uftp_h *header;
    struct abort_h *abort;
    int payloadlen;

    buf = calloc(mtu, 1);
    if (buf == NULL) {
        syserror(0, 0, "calloc failed!");
        exit(1);
    }
    header = (struct uftp_h *)buf;
    abort = (struct abort_h *)(buf + sizeof(struct uftp_h));

    set_uftp_header(header, ABORT, finfo, destaddr);
    abort->func = ABORT;
    if (dest) {
        abort->host = dest->s_addr;
    }
    strncpy(abort->message, message, sizeof(abort->message) - 1);

    payloadlen = sizeof(struct abort_h);
    if (encrypt) {
        encrypted = NULL;
        if (!encrypt_and_sign(buf, &encrypted, payloadlen, mtu, keytype,
                groupkey, groupsalt, ivlen, hashtype, grouphmackey, hmaclen,
                sigtype, privkey, rsalen)) {
            log0(0, 0, "Error encrypting ABORT");
            free(buf);
            return;
        }
        outpacket = encrypted;
        payloadlen = ntohs(((struct uftp_h *)outpacket)->blsize);
    } else {
        encrypted = NULL;
        outpacket = buf;
        header->blsize = htons(payloadlen);
    }

    if (nb_sendto(sock, outpacket, payloadlen + sizeof(struct uftp_h), 0,
               (struct sockaddr *)destaddr,
               sizeof(struct sockaddr_in)) == SOCKET_ERROR) {
        sockerror(0, 0, "Error sending ABORT");
    }
    free(buf); 
    free(encrypted);
} 
Beispiel #8
0
/**
 * Sends an ABORT message upstream to a server
 */
void send_upstream_abort(int listidx, uint32_t addr, const char *message)
{
    unsigned char *buf;
    struct uftp_h *header;
    struct abort_h *abort;
    int payloadlen;

    buf = calloc(group_list[listidx].mtu, 1);
    if (buf == NULL) {
        syserror(0, 0, "calloc failed!");
        exit(1);
    }

    header = (struct uftp_h *)buf;
    abort = (struct abort_h *)(buf + sizeof(struct uftp_h));

    set_uftp_header(header, ABORT, listidx);
    if (!group_list[listidx].foundaddr) {
        header->srcaddr = m_interface[0].addr.s_addr;
    }
    header->destaddr = group_list[listidx].srcaddr.s_addr;
    abort->func = ABORT;
    abort->host = addr;
    strncpy(abort->message, message, sizeof(abort->message) - 1);
    header->blsize = htons(sizeof(struct abort_h));
    payloadlen = sizeof(struct uftp_h) + sizeof(struct abort_h);

    // Proxies should never need to send an encrypted ABORT

    if (nb_sendto(listener, buf, payloadlen, 0,
               (struct sockaddr *)&group_list[listidx].up_addr,
               sizeof(struct sockaddr_in)) == SOCKET_ERROR) {
        sockerror(group_list[listidx].group_id, 0, "Error sending ABORT");
    }

    if (addr == 0) {
        group_cleanup(listidx);
    }
    free(buf);
}
Beispiel #9
0
/**
 * Sends a KEY_REQ message to the proxy specified as the reply proxy
 */
void send_key_req()
{
    unsigned char *packet;
    struct uftp_h *header;
    struct key_req_h *keyreq;
    union sockaddr_u proxyaddr;
    char addrname[INET6_ADDRSTRLEN];
    int meslen, rval;

    packet = safe_calloc(sizeof(struct uftp_h) + sizeof(struct key_req_h), 1);

    header = (struct uftp_h *)packet;
    keyreq = (struct key_req_h *)(packet + sizeof(struct uftp_h));
    header->version = UFTP_VER_NUM;
    header->func = KEY_REQ;
    header->src_id = uid;
    keyreq->func = KEY_REQ;
    keyreq->hlen = sizeof(struct key_req_h) / 4;

    meslen = sizeof(struct uftp_h) + sizeof(struct key_req_h);
    proxyaddr = proxy_info.addr;
    if (nb_sendto(listener, packet, meslen, 0, 
                  (struct sockaddr *)&proxyaddr,
                  family_len(proxyaddr)) == SOCKET_ERROR) {
        sockerror(0, 0, 0, "Error sending KEY_REQ");
    } else {
        if ((rval = getnameinfo((struct sockaddr *)&proxyaddr,
                family_len(proxyaddr), addrname, sizeof(addrname),
                NULL, 0, NI_NUMERICHOST)) != 0) {
            log1(0, 0, 0, "getnameinfo failed: %s", gai_strerror(rval));
        }

        log2(0, 0, 0, "Sent KEY_REQ to %s:%s", addrname, portname);
    }

    free(packet);
    gettimeofday(&next_keyreq_time, NULL);
    next_keyreq_time.tv_sec += KEY_REQ_INT;
}
Beispiel #10
0
/**
 * Sends an ABORT message downstream to clients
 */
void send_downstream_abort(int listidx, uint32_t addr, const char *message)
{
    unsigned char *buf;
    struct uftp_h *header;
    struct abort_h *abort;
    struct sockaddr_in sin;
    int payloadlen;

    buf = calloc(group_list[listidx].mtu, 1);
    if (buf == NULL) {
        syserror(0, 0, "calloc failed!");
        exit(1);
    }

    header = (struct uftp_h *)buf;
    abort = (struct abort_h *)(buf + sizeof(struct uftp_h));

    set_uftp_header(header, ABORT, listidx);
    header->destaddr = group_list[listidx].multi.s_addr;
    abort->func = ABORT;
    abort->host = addr;
    strncpy(abort->message, message, sizeof(abort->message) - 1);
    header->blsize = htons(sizeof(struct abort_h));
    payloadlen = sizeof(struct uftp_h) + sizeof(struct abort_h);

    // Proxies should never need to send an encrypted ABORT

    memset(&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_addr = group_list[listidx].multi;
    sin.sin_port = htons(out_port);
    if (nb_sendto(listener, buf, payloadlen, 0, (struct sockaddr *)&sin,
               sizeof(struct sockaddr_in)) == SOCKET_ERROR) {
        sockerror(group_list[listidx].group_id, 0, "Error sending ABORT");
    }

    free(buf);
}
Beispiel #11
0
/**
 * Sends a KEY_REQ message to the proxy specified as the reply proxy
 */
void send_key_req()
{
    unsigned char *packet;
    struct uftp_h *header;
    struct key_req_h *keyreq;
    struct sockaddr_in proxyaddr;
    int meslen;

    packet = calloc(sizeof(struct uftp_h) + sizeof(struct key_req_h), 1);
    if (packet == NULL) {
        syserror(0, 0, "calloc failed!");
        exit(1);
    }

    header = (struct uftp_h *)packet;
    keyreq = (struct key_req_h *)(packet + sizeof(struct uftp_h));
    header->uftp_id = UFTP_VER_NUM;
    header->func = KEY_REQ;
    keyreq->func = KEY_REQ;

    meslen = sizeof(struct key_req_h);
    header->blsize = htons(meslen);
    meslen += sizeof(struct uftp_h);
    proxyaddr.sin_family = AF_INET;
    proxyaddr.sin_addr = proxy_info.addr;
    proxyaddr.sin_port = htons(port);
    if (nb_sendto(listener, packet, meslen, 0, 
                  (struct sockaddr *)&proxyaddr,
                  sizeof(struct sockaddr_in)) == SOCKET_ERROR) {
        sockerror(0, 0, "Error sending KEY_REQ");
    } else {
        log(0, 0, "Sent KEY_REQ to %s:%d", inet_ntoa(proxy_info.addr), port);
    }

    free(packet);
    gettimeofday(&next_keyreq_time, NULL);
    next_keyreq_time.tv_sec += KEY_REQ_INT;
}
Beispiel #12
0
/**
 * Sends an HB_RESP in response to an HB_REQ
 */
void send_hb_response(const union sockaddr_u *src, int response)
{
    unsigned char *packet;
    struct uftp_h *header;
    struct hb_resp_h *hbresp;
    char destname[INET6_ADDRSTRLEN], destport[PORTNAME_LEN];
    int meslen, rval;

    packet = safe_calloc(sizeof(struct uftp_h) + sizeof(struct hb_resp_h), 1);

    header = (struct uftp_h *)packet;
    hbresp = (struct hb_resp_h *)(packet + sizeof(struct uftp_h));
    header->version = UFTP_VER_NUM;
    header->func = HB_RESP;
    header->src_id = uid;
    hbresp->func = HB_RESP;
    hbresp->hlen = sizeof(struct hb_resp_h) / 4;
    hbresp->authenticated = response;
    if (response == HB_AUTH_CHALLENGE) {
        hbresp->nonce = htonl(down_nonce);
    }

    meslen = sizeof(struct uftp_h) + sizeof(struct hb_resp_h);
    if (nb_sendto(listener, packet, meslen, 0, (const struct sockaddr *)src,
                  family_len(*src)) == SOCKET_ERROR) {
        sockerror(0, 0, 0, "Error sending HB_RESP");
    } else {
        if ((rval = getnameinfo((const struct sockaddr *)src,
                family_len(*src), destname, sizeof(destname), destport,
                sizeof(destport), NI_NUMERICHOST | NI_NUMERICSERV)) != 0) {
            log1(0, 0, 0, "getnameinfo failed: %s", gai_strerror(rval));
        }
        log2(0, 0, 0, "Sent HB_RESP to %s:%s", destname, destport);
    }
    free(packet);
}
Beispiel #13
0
/**
 * Sends an ABORT message upstream to a server
 */
void send_upstream_abort(struct pr_group_list_t *group, uint32_t addr,
                         const char *message)
{
    unsigned char *buf;
    struct uftp_h *header;
    struct abort_h *abort_hdr;
    int payloadlen;

    buf = safe_calloc(MAXMTU, 1);

    header = (struct uftp_h *)buf;
    abort_hdr = (struct abort_h *)(buf + sizeof(struct uftp_h));

    set_uftp_header(header, ABORT, group);
    header->seq = group->send_seq_up++;
    header->src_id = uid;
    abort_hdr->func = ABORT;
    abort_hdr->hlen = sizeof(struct abort_h) / 4;
    abort_hdr->flags = 0;
    abort_hdr->host = addr;
    strncpy(abort_hdr->message, message, sizeof(abort_hdr->message) - 1);
    payloadlen = sizeof(struct uftp_h) + sizeof(struct abort_h);

    // Proxies should never need to send an encrypted ABORT

    if (nb_sendto(listener, buf, payloadlen, 0,
               (struct sockaddr *)&group->up_addr,
               family_len(group->up_addr)) == SOCKET_ERROR) {
        gsockerror(group, "Error sending ABORT");
    }

    if (addr == 0) {
        group_cleanup(group);
    }
    free(buf);
}
Beispiel #14
0
/**
 * Sends back a STATUS message with the given NAK list
 */
void send_status(struct group_list_t *group, unsigned int section,
                 const unsigned char *naks, unsigned int nak_count)
{
    unsigned char *buf, *encrypted, *outpacket;
    struct uftp_h *header;
    struct status_h *status;
    struct tfmcc_ack_info_he *tfmcc;
    unsigned char *sent_naks;
    int payloadlen, enclen;

    buf = safe_calloc(MAXMTU, 1);

    header = (struct uftp_h *)buf;
    status = (struct status_h *)(buf + sizeof(struct uftp_h));
    tfmcc = (struct tfmcc_ack_info_he *)((unsigned char *)status +
                sizeof(struct status_h));

    set_uftp_header(header, STATUS, group);
    status->func = STATUS;
    if (group->cc_type == CC_TFMCC) {
        status->hlen =
              (sizeof(struct status_h) + sizeof(struct tfmcc_ack_info_he)) / 4;
    } else {
        status->hlen = sizeof(struct status_h) / 4;
    }
    status->file_id = htons(group->file_id);
    status->section = htons(section);
    if (section >= group->fileinfo.big_sections) {
        payloadlen = (group->fileinfo.secsize_small / 8) + 1;
    } else {
        payloadlen = (group->fileinfo.secsize_big / 8) + 1;
    }
    if (group->cc_type == CC_TFMCC) {
        set_tfmcc_ack_info(group, tfmcc);
    }
    sent_naks = (unsigned char *)status + (status->hlen * 4);
    memcpy(sent_naks, naks, payloadlen);

    payloadlen += status->hlen * 4;
    if ((group->phase != PHASE_REGISTERED) && (group->keytype != KEY_NONE)) {
        encrypted = NULL;
        if (!encrypt_and_sign(buf, &encrypted, payloadlen, &enclen,
                group->keytype, group->groupkey, group->groupsalt,&group->ivctr,
                group->ivlen, group->hashtype, group->grouphmackey,
                group->hmaclen, group->sigtype, group->keyextype,
                group->client_privkey, group->client_privkeylen)) {
            glog0(group, "Error encrypting STATUS");
            free(buf);
            return;
        }
        outpacket = encrypted;
        payloadlen = enclen;
    } else {
        encrypted = NULL;
        outpacket = buf;
    }
    payloadlen += sizeof(struct uftp_h);

    if (nb_sendto(listener, outpacket, payloadlen, 0,
               (struct sockaddr *)&group->replyaddr,
               family_len(group->replyaddr)) == SOCKET_ERROR) {
        gsockerror(group, "Error sending STATUS");
    } else {
        glog2(group, "Sent %d NAKs for section %d", nak_count, section);
    }

    free(buf);
    free(encrypted);
}
Beispiel #15
0
/**
 * Send a KEYINFO message.  Sent during the Announce phase for a group
 * with encryption enabled.
 * Returns 1 on success, 0 on fail.
 */
int send_keyinfo(const struct finfo_t *finfo, int attempt)
{
    unsigned char *buf, *iv;
    struct uftp_h *header;
    struct keyinfo_h *keyinfo;
    struct destkey *keylist;
    unsigned int hsize, payloadlen, len;
    int maxdest, packetcnt, dests, iv_init, i;
    int unauth_keytype, unauth_keylen, unauth_ivlen;

    // Don't use a cipher in an authentication mode to encrypt the group master
    unauth_keytype = unauth_key(keytype);
    get_key_info(unauth_keytype, &unauth_keylen, &unauth_ivlen);

    buf = safe_calloc(MAXMTU, 1);
    iv = safe_calloc(unauth_ivlen, 1);
    header = (struct uftp_h *)buf;
    keyinfo = (struct keyinfo_h *)(buf + sizeof(struct uftp_h));
    keylist = (struct destkey *)((char *)keyinfo + sizeof(struct keyinfo_h));

    set_uftp_header(header, KEYINFO, finfo->group_id, finfo->group_inst,
                    grtt, destcount);
    keyinfo->func = KEYINFO;
    keyinfo->hlen = sizeof(struct keyinfo_h) / 4;
    keylist = (struct destkey *)((uint8_t *)keyinfo + (keyinfo->hlen * 4));

    iv_init = 0;
    hsize = sizeof(struct keyinfo_h);
    maxdest = blocksize / sizeof(struct destkey);
    packetcnt = 1;
    for (i = 0, dests = 0; i < destcount; i++) {
        if (destlist[i].status == DEST_REGISTERED) {
            if (!iv_init) {
                ivctr++;
                keyinfo->iv_ctr_hi =htonl((ivctr & 0xFFFFFFFF00000000LL) >> 32);
                keyinfo->iv_ctr_lo = htonl(ivctr & 0x00000000FFFFFFFFLL);
                iv_init = 1;
            }
            keylist[dests].dest_id = destlist[i].id;
            build_iv(iv, destlist[i].encinfo->salt, unauth_ivlen,
                     uftp_htonll(ivctr), header->src_id);
            if (!encrypt_block(unauth_keytype, iv,destlist[i].encinfo->key,
                               NULL,0, &groupmaster[1], sizeof(groupmaster) - 1,
                               keylist[dests].groupmaster, &len)) {
                glog0(finfo, "Error encrypting KEYINFO for %s",
                             destlist[i].name);
                free(buf);
                free(iv);
                return 0;
            }
            dests++;
        }
        if ((dests >= maxdest) || ((i == destcount - 1) && (dests > 0))) {
            header->seq = htons(send_seq++);
            payloadlen = hsize + (dests * sizeof(struct destkey));
            glog2(finfo, "Sending KEYINFO %d.%d", attempt, packetcnt);
            if (nb_sendto(sock, buf, payloadlen + sizeof(struct uftp_h), 0,
                          (struct sockaddr *)&receive_dest,
                          family_len(receive_dest)) == SOCKET_ERROR) {
                gsockerror(finfo, "Error sending KEYINFO");
                sleep(1);
                free(buf);
                free(iv);
                return 0;
            }
            if (packet_wait) usleep(packet_wait);
            memset(keylist, 0, maxdest * sizeof(struct destkey));
            iv_init = 0;
            dests = 0;
            packetcnt++;
        }
    }
Beispiel #16
0
/**
 * Send the ANNOUNCE message
 * For open group membership, just send one.  For closed group membership,
 * list as many destinations as will fit and send multiple packets so that
 * each receiver is listed.
 * Returns 1 on success, 0 on fail.
 */
int send_announce(const struct finfo_t *finfo, int attempt, int open)
{
    int packetlen, rval, iplen, extlen;
    unsigned char *buf;
    struct uftp_h *header;
    struct announce_h *announce;
    unsigned char *publicaddr, *privateaddr;
    struct enc_info_he *encinfo;
    struct timeval tv;
    uint32_t *idlist;

    buf = safe_calloc(MAXMTU, 1); 
    if (listen_dest.ss.ss_family == AF_INET6) {
        iplen = sizeof(struct in6_addr);
    } else {
        iplen = sizeof(struct in_addr);
    }
    header = (struct uftp_h *)buf;
    announce = (struct announce_h *)(buf + sizeof(struct uftp_h));
    publicaddr = (unsigned char *)announce + sizeof(struct announce_h);
    privateaddr = publicaddr + iplen;
    encinfo = (struct enc_info_he *)(privateaddr + iplen);

    set_uftp_header(header, ANNOUNCE, finfo->group_id, finfo->group_inst,
                    grtt, destcount);
    announce->func = ANNOUNCE;
    if (sync_mode) {
        announce->flags |= FLAG_SYNC_MODE;
        if (sync_preview) {
            announce->flags |= FLAG_SYNC_PREVIEW;
        }
    }
    announce->robust = robust;
    announce->cc_type = cc_type;
    announce->blocksize = htons(blocksize);
    gettimeofday(&tv, NULL);
    announce->tstamp_sec = htonl(tv.tv_sec);
    announce->tstamp_usec = htonl(tv.tv_usec);
    if (!is_multicast(&listen_dest, 0)) {
        memset(publicaddr, 0, iplen);
        memset(privateaddr, 0, iplen);
    } else if (listen_dest.ss.ss_family == AF_INET6) {
        memcpy(publicaddr, &listen_dest.sin6.sin6_addr.s6_addr, iplen);
        memcpy(privateaddr, &receive_dest.sin6.sin6_addr.s6_addr, iplen);
    } else {
        memcpy(publicaddr, &listen_dest.sin.sin_addr.s_addr, iplen);
        memcpy(privateaddr, &receive_dest.sin.sin_addr.s_addr, iplen);
    }
    if (listen_dest.ss.ss_family == AF_INET6) {
        announce->flags |= FLAG_IPV6;
    }

    if (keytype != KEY_NONE) {
        extlen = set_enc_info(finfo, encinfo);
        if (extlen == 0) {
            glog0(finfo, "Error setting up EXT_ENC_INFO");
            free(buf);
            return 0;
        }
        announce->hlen = (sizeof(struct announce_h) +
                          iplen + iplen + extlen) / 4;
    } else {
        announce->hlen = (sizeof(struct announce_h) + iplen + iplen) / 4;
    }

    idlist = (uint32_t *)((uint8_t *)announce + (announce->hlen * 4));
    if (open) {
        header->seq = htons(send_seq++);
        packetlen = sizeof(struct uftp_h) + (announce->hlen * 4);
        if (!sign_announce(finfo, buf, packetlen)) {
            glog0(finfo, "Error signing ANNOUNCE");
            free(buf);
            return 0;
        }
        glog2(finfo, "Sending ANNOUNCE %d", attempt);
        if (nb_sendto(sock, buf, packetlen, 0, (struct sockaddr *)&listen_dest,
                      family_len(listen_dest)) == SOCKET_ERROR) {
            gsockerror(finfo, "Error sending ANNOUNCE");
            // So we don't spin our wheels...
            sleep(1);
            free(buf);
            return 0;
        }
        free(buf);
        return 1;
    } else {
        rval = send_multiple(finfo, buf, ANNOUNCE, attempt, idlist,
                DEST_MUTE, 0, &listen_dest, 0);
        free(buf);
        return rval;
    }
}
Beispiel #17
0
/**
 * Sends an ABORT message to a server
 */
void send_abort(int listidx, const char *message)
{
    unsigned char *buf, *encrypted, *outpacket;
    struct uftp_h *header;
    struct abort_h *abort;
    struct uftp2_h *v2_header;
    char *v2_message;
    int payloadlen;

    buf = calloc(group_list[listidx].mtu, 1);
    if (buf == NULL) {
        syserror(0, 0, "calloc failed!");
        exit(1);
    }

    if (group_list[listidx].version == UFTP_V2_VER) {
        v2_header = (struct uftp2_h *)buf;
        v2_message = (char *)v2_header + sizeof(struct uftp2_h);

        v2_header->uftp_id = htonl(V2_UFTP_ID);
        v2_header->func = htonl(V2_ABORT);
        v2_header->tx_id = htonl(group_list[listidx].group_id);
        v2_header->blsize = htonl(strlen(message));
        payloadlen = sizeof(struct uftp2_h) + strlen(message);
        strncpy(v2_message, message, V2_BLOCKSIZE - 1);
        encrypted = NULL;
        outpacket = buf;
    } else {
        header = (struct uftp_h *)buf;
        abort = (struct abort_h *)(buf + sizeof(struct uftp_h));

        set_uftp_header(header, ABORT, listidx);
        abort->func = ABORT;
        abort->host = 0;
        strncpy(abort->message, message, sizeof(abort->message) - 1);

        payloadlen = sizeof(struct abort_h);
        if ((group_list[listidx].phase != PHASE_REGISTERED) &&
                (group_list[listidx].keytype != KEY_NONE)) {
            encrypted = NULL;
            if (!encrypt_and_sign(buf, &encrypted, payloadlen,
                    group_list[listidx].mtu, group_list[listidx].keytype,
                    group_list[listidx].groupkey, group_list[listidx].groupsalt,
                    group_list[listidx].ivlen, group_list[listidx].hashtype,
                    group_list[listidx].grouphmackey,
                    group_list[listidx].hmaclen, group_list[listidx].sigtype,
                    group_list[listidx].clientkey,
                    group_list[listidx].client_keylen)) {
                log0(0, 0, "Error encrypting ABORT");
                free(buf);
                return;
            }
            outpacket = encrypted;
            payloadlen = ntohs(((struct uftp_h *)outpacket)->blsize);
        } else {
            encrypted = NULL;
            outpacket = buf;
            header->blsize = htons(payloadlen);
        }
        payloadlen += sizeof(struct uftp_h);
    }

    if (nb_sendto(listener, outpacket, payloadlen, 0,
               (struct sockaddr *)&group_list[listidx].replyaddr,
               sizeof(struct sockaddr_in)) == SOCKET_ERROR) {
        sockerror(group_list[listidx].group_id, group_list[listidx].file_id,
                "Error sending ABORT");
    }

    file_cleanup(listidx, 1);
    free(buf);
    free(encrypted);
}
Beispiel #18
0
/**
 * For messages that send a list of clients in the body, append all clients
 * in the specified state to the packet, then send the message of the given
 * type when either the body is full or the end of the client list has been
 * reached.  All header fields besides uftp_h.blsize and message.destcount
 * must be populated before calling.
 * Returns 1 on success, 0 on fail.
 */
int send_multiple(const struct finfo_t *finfo, unsigned char *packet,
                  int message, int attempt, uint32_t *addrlist, int state,
                  uint16_t *mes_destcount, int encrypt,
                  const struct sockaddr_in *destaddr, int regconf)
{
    struct uftp_h *header;
    int hsize, payloadlen;
    int maxdest, packetcnt, dests, i;
    unsigned char *mheader, *encpacket, *outpacket;

    header = (struct uftp_h *)packet;
    mheader = packet + sizeof(struct uftp_h);
    hsize = (unsigned char *)addrlist - mheader;
    maxdest = ((encrypt ? encpayloadsize : payloadsize) - hsize) /
              sizeof(struct in_addr);
    packetcnt = 1;
    if (encrypt) {
        encpacket = calloc(mtu + keylen, 1); 
        if (encpacket == NULL) {
            syserror(0, 0, "calloc failed!");
            exit(1);
        }
    } else {
        encpacket = NULL;
    }
    for (i = 0, dests = 0; i < destcount; i++) {
        if (message == REG_CONF) {
            // Only send REG_CONF for a particular client if either it's
            // behind a proxy or we're sending them to everyone.
            // Also, don't send if we already sent one and we haven't
            // gotten another REGISTER
            if ((destlist[i].status == state) &&
                    (!finfo->deststate[i].conf_sent) &&
                    (regconf || (destlist[i].proxyidx != -1))) {
                addrlist[dests++] = destlist[i].addr.s_addr;
                finfo->deststate[i].conf_sent = 1;
            }
        } else if (message == DONE_CONF) {
            // As with REG_CONF, don't send a DONE_CONF for a client
            // if we already sent one and we haven't gotten another COMPLETE
            if ((destlist[i].status == state) &&
                    (!finfo->deststate[i].conf_sent)) {
                addrlist[dests++] = destlist[i].addr.s_addr;
                finfo->deststate[i].conf_sent = 1;
            }
        } else if (destlist[i].status == state) {
            addrlist[dests++] = destlist[i].addr.s_addr;
        }
        if ((dests >= maxdest) || ((i == destcount - 1) && (dests > 0))) {
            payloadlen = hsize + (dests * sizeof(uint32_t));
            *mes_destcount = htons(dests);
            if (encrypt) {
                if (!encrypt_and_sign(packet, &encpacket, payloadlen, mtu,
                        keytype, groupkey, groupsalt, ivlen, hashtype,
                        grouphmackey, hmaclen, sigtype, privkey, rsalen)) {
                    log0(0, 0, "Error encrypting %s", func_name(message));
                    free(encpacket);
                    return 0;
                }
                outpacket = encpacket;
                payloadlen = ntohs(((struct uftp_h *)outpacket)->blsize);
            } else {
                outpacket = packet;
                header->blsize = htons(payloadlen);
            }
            log2(0, 0, "Sending %s %d.%d", func_name(message), 
                       attempt, packetcnt);
            log4(0, 0, "Sending to %08X", ntohl(destaddr->sin_addr.s_addr));
            if (nb_sendto(sock, outpacket, payloadlen + sizeof(struct uftp_h),0,
                       (struct sockaddr *)destaddr,
                       sizeof(*destaddr)) == SOCKET_ERROR) {
                sockerror(0, 0, "Error sending %s", func_name(message));
                sleep(1);
                free(encpacket);
                return 0;
            }
            if (packet_wait) usleep(packet_wait);
            memset(addrlist, 0, maxdest * sizeof(uint32_t));
            dests = 0;
            packetcnt++;
        }
    }
    free(encpacket);
    return 1;
}
Beispiel #19
0
/**
 * Sends a PROXY_KEY message to the first listed public multicast address.
 */
void send_proxy_key()
{
    unsigned char *packet, *keyblob, *dhblob, *sig;
    struct uftp_h *header;
    struct proxy_key_h *proxykey;
    uint32_t nonce;
    unsigned int meslen, siglen;
    uint16_t bloblen, dhlen;
    char pubname[INET6_ADDRSTRLEN];
    int rval;

    packet = safe_calloc(sizeof(struct uftp_h) + sizeof(struct hb_req_h) +
                    (PUBKEY_LEN * 3) , 1);

    header = (struct uftp_h *)packet;
    proxykey = (struct proxy_key_h *)(packet + sizeof(struct uftp_h));
    keyblob = (unsigned char *)proxykey + sizeof(struct proxy_key_h);
    header->version = UFTP_VER_NUM;
    header->func = PROXY_KEY;
    header->src_id = uid;
    proxykey->func = PROXY_KEY;
    nonce = htonl(rand32());
    proxykey->nonce = nonce;

    if (privkey_type[0] == KEYBLOB_RSA) {
        if (!export_RSA_key(privkey[0].rsa, keyblob, &bloblen)) {
            log0(0, 0, 0, "Error exporting public key");
            free(packet);
            return;
        }
    } else {
        if (!export_EC_key(privkey[0].ec, keyblob, &bloblen)) {
            log0(0, 0, 0, "Error exporting public key");
            free(packet);
            return;
        }
    }
    dhblob = keyblob + bloblen;
    if (dhkey.key) {
        if (!export_EC_key(dhkey.ec, dhblob, &dhlen)) {
            log0(0, 0, 0, "Error exporting public key");
            free(packet);
            return;
        }
    } else {
        dhlen = 0;
    }
    sig = dhblob + dhlen;
    if (privkey_type[0] == KEYBLOB_RSA) {
        if (!create_RSA_sig(privkey[0].rsa, HASH_SHA1, (unsigned char *)&nonce,
                            sizeof(nonce), sig, &siglen)) {
            log0(0, 0, 0, "Error signing nonce");
            free(packet);
            return;
        }
    } else {
        if (!create_ECDSA_sig(privkey[0].ec, HASH_SHA1, (unsigned char *)&nonce,
                              sizeof(nonce), sig, &siglen)) {
            log0(0, 0, 0, "Error signing nonce");
            free(packet);
            return;
        }
    }
    proxykey->bloblen = htons(bloblen);
    proxykey->dhlen = htons(dhlen);
    proxykey->siglen = htons(siglen);
    proxykey->hlen = (sizeof(struct proxy_key_h) + bloblen + dhlen + siglen)/4;

    meslen = sizeof(struct uftp_h) + (proxykey->hlen * 4);
    if (nb_sendto(listener, packet, meslen, 0, 
                  (struct sockaddr *)&pub_multi[0],
                  family_len(pub_multi[0])) == SOCKET_ERROR) {
        sockerror(0, 0, 0, "Error sending PROXY_KEY");
    } else {
        if ((rval = getnameinfo((struct sockaddr *)&pub_multi[0],
                family_len(pub_multi[0]), pubname, sizeof(pubname), NULL, 0,
                NI_NUMERICHOST)) != 0) {
            log1(0, 0, 0, "getnameinfo failed: %s", gai_strerror(rval));
        }
        log2(0, 0, 0, "Sent PROXY_KEY to %s", pubname);
    }
    free(packet);
}
Beispiel #20
0
/**
 * Sends a FILEINFO_ACK in response to a FILEINFO
 */
void send_fileinfo_ack(struct group_list_t *group, int restart)
{
    unsigned char *buf, *encrypted, *outpacket;
    struct uftp_h *header;
    struct fileinfoack_h *fileinfo_ack;
    struct timeval now, send_time;
    unsigned int payloadlen;
    int enclen;

    buf = safe_calloc(MAXMTU, 1);

    header = (struct uftp_h *)buf;
    fileinfo_ack = (struct fileinfoack_h *)(buf + sizeof(struct uftp_h));

    payloadlen = sizeof(struct fileinfoack_h);
    set_uftp_header(header, FILEINFO_ACK, group);
    fileinfo_ack->func = FILEINFO_ACK;
    fileinfo_ack->hlen = sizeof(struct fileinfoack_h) / 4;
    fileinfo_ack->file_id = htons(group->file_id);
    if (restart) {
        fileinfo_ack->flags |= FLAG_PARTIAL;
    }
    gettimeofday(&now, NULL);
    if (cmptimestamp(now, group->last_server_rx_ts) <= 0) {
        send_time = group->last_server_ts;
    } else {
        send_time = add_timeval(group->last_server_ts,
                diff_timeval(now, group->last_server_rx_ts));
    }
    fileinfo_ack->tstamp_sec = htonl((uint32_t)send_time.tv_sec);
    fileinfo_ack->tstamp_usec = htonl((uint32_t)send_time.tv_usec);
    if (group->keytype != KEY_NONE) {
        encrypted = NULL;
        if (!encrypt_and_sign(buf, &encrypted, payloadlen, &enclen,
                group->keytype, group->groupkey, group->groupsalt,&group->ivctr,
                group->ivlen, group->hashtype, group->grouphmackey,
                group->hmaclen, group->sigtype, group->keyextype,
                group->client_privkey, group->client_privkeylen)) {
            glog0(group, "Error encrypting FILEINFO_ACK");
            free(buf);
            return;
        }
        outpacket = encrypted;
        payloadlen = enclen;
    } else {
        encrypted = NULL;
        outpacket = buf;
    }
    payloadlen += sizeof(struct uftp_h);

    if (nb_sendto(listener, outpacket, payloadlen, 0,
               (struct sockaddr *)&(group->replyaddr),
               family_len(group->replyaddr)) == SOCKET_ERROR) {
        gsockerror(group, "Error sending FILEINFO_ACK");
    } else {
        glog2(group, "FILEINFO_ACK sent");
    }
    glog3(group, "send time: %d.%06d", send_time.tv_sec, send_time.tv_usec);
    free(encrypted);
    free(buf);
}
Beispiel #21
0
/**
 * Sends a REGISTER message in response to an ANNOUNCE or on timeout when
 * waiting for a KEYINFO or REG_CONF.  If the register timeout expired, abort.
 */
void send_register(struct group_list_t *group)
{
    struct uftp_h *header;
    struct register_h *reg;
    unsigned char *buf, *keydata;
    struct timeval now, send_time;
    unsigned int len, meslen;
    union key_t key;

    gettimeofday(&now, NULL);
    if (cmptimestamp(now, group->expire_time) >= 0) {
        glog1(group, "Registration unconfirmed by server");
        send_abort(group, "Registration unconfirmed");
        return;
    }

    buf = safe_calloc(MAXMTU, 1);

    header = (struct uftp_h *)buf;
    reg = (struct register_h *)(buf + sizeof(struct uftp_h));
    keydata = (unsigned char *)reg + sizeof(struct register_h);
    set_uftp_header(header, REGISTER, group);
    reg->func = REGISTER;
    if (group->keytype != KEY_NONE) {
        memcpy(reg->rand2, group->rand2, RAND_LEN);
        if (group->keyextype == KEYEX_RSA) {
            if (has_proxy) {
                key = proxy_pubkey;
            } else {
                key = group->server_pubkey;
            }
            if (!RSA_encrypt(key.rsa, group->premaster, group->premaster_len,
                             keydata, &len)) {
                glog0(group, "Error encrypting premaster secret");
                send_abort(group, "Error encrypting premaster secret");
                free(buf);
                return;
            }
        } else {
            uint16_t keylen;
            if (!export_EC_key(group->client_dhkey.ec, keydata, &keylen)) {
                glog0(group, "Error exporting ECDH public key");
                send_abort(group, "Error exporting ECDH public key");
                free(buf);
                return;
            }
            len = keylen;
        }
        reg->keyinfo_len = htons(len); 
    } else {
        len = 0;
    }
    gettimeofday(&now, NULL);
    if (cmptimestamp(now, group->last_server_rx_ts) <= 0) {
        send_time = group->last_server_ts;
    } else {
        send_time = add_timeval(group->last_server_ts,
                diff_timeval(now, group->last_server_rx_ts));
    }
    reg->tstamp_sec = htonl((uint32_t)send_time.tv_sec);
    reg->tstamp_usec = htonl((uint32_t)send_time.tv_usec);
    reg->hlen = (sizeof(struct register_h) + len) / 4;
    meslen = sizeof(struct uftp_h) + (reg->hlen * 4);

    if (nb_sendto(listener, buf, meslen, 0,
               (struct sockaddr *)&(group->replyaddr),
               family_len(group->replyaddr)) == SOCKET_ERROR) {
        gsockerror(group, "Error sending REGISTER");
    } else {
        glog2(group, "REGISTER sent");
    }
    glog3(group, "send time: %d.%06d", send_time.tv_sec, send_time.tv_usec);

    set_timeout(group, 0);
    if (group->client_auth) {
        send_client_key(group);
    }
    free(buf);
}
Beispiel #22
0
/**
 * Forward a message unmodified to the next hop, resigning if necessary.
 */
void forward_message(struct pr_group_list_t *group,
                     const union sockaddr_u *src,
                     unsigned char *packet, int packetlen)
{
    struct uftp_h *header;
    struct encrypted_h *encrypted;
    struct announce_h *announce;
    struct enc_info_he *encinfo;
    union sockaddr_u dest;
    unsigned int meslen, siglen;
    int hostidx, rval, iplen, resign;
    char destname[INET6_ADDRSTRLEN], destport[PORTNAME_LEN];
    uint8_t *sig, *sigcopy;
    union key_t key;

    header = (struct uftp_h *)packet;
    meslen = (unsigned int)packetlen;

    memset(&dest, 0, sizeof(dest));
    if (!memcmp(src, &group->up_addr, sizeof(*src))) {
        if (proxy_type == RESPONSE_PROXY) {
            // Response proxy, no downstream forwarding
            set_timeout(group, 0, 0);
            return;
        } else if (proxy_type == SERVER_PROXY) {
            dest = down_addr;
        } else {
            if (header->func == ANNOUNCE) {
                dest = group->publicmcast;
            } else {
                dest = group->privatemcast;
            }
            key = group->server_pubkey;
        }
    } else {
        dest = group->up_addr;
        if (proxy_type != SERVER_PROXY) {
            hostidx = find_client(group, header->src_id);
            if (hostidx == -1) {
                glog1(group, "Couldn't find receiver in list");
                return;
            }
            key = group->destinfo[hostidx].pubkey;
        }
    }

    // If we're using KEYEX signatures, or sending an ANNOUNCE with ECDH,
    // verify the signature and resign
    resign = 0;
    if ((proxy_type != SERVER_PROXY) && (header->func == ENCRYPTED) &&
            (group->sigtype == SIG_KEYEX)) {
        encrypted = (struct encrypted_h *)(packet + sizeof(struct uftp_h));
        sig = (uint8_t *)encrypted + sizeof(struct encrypted_h);
        siglen = ntohs(encrypted->sig_len);
        resign = 1;
    } else if ((proxy_type != SERVER_PROXY) && (header->func == ANNOUNCE) &&
            ((group->keyextype == KEYEX_ECDH_RSA) ||
             (group->keyextype == KEYEX_ECDH_ECDSA))) {
        announce = (struct announce_h *)(packet + sizeof(struct uftp_h));
        iplen = ((announce->flags & FLAG_IPV6) != 0) ? 16 : 4;
        encinfo = (struct enc_info_he *) ((uint8_t *)announce +
                sizeof(struct announce_h) + iplen + iplen);
        sig = (uint8_t *)encinfo + sizeof(struct enc_info_he) +
                ntohs(encinfo->keylen) + ntohs(encinfo->dhlen);
        siglen = ntohs(encinfo->siglen);
        resign = 1;
    }
    if (resign) {
        sigcopy = safe_calloc(siglen, 1);
        memcpy(sigcopy, sig, siglen);
        memset(sig, 0, siglen);
        if ((group->keyextype == KEYEX_RSA) ||
                (group->keyextype == KEYEX_ECDH_RSA)) {
            if (header->func == ENCRYPTED) {
                if (!verify_RSA_sig(key.rsa, group->hashtype, packet,
                                    meslen, sigcopy, siglen)) {
                    glog1(group, "Signature verification failed");
                    free(sigcopy);
                    return;
                }
            }
            if (!create_RSA_sig(group->proxy_privkey.rsa, group->hashtype,
                                packet, meslen, sigcopy, &siglen)) {
                glog0(group, "Signature creation failed");
                free(sigcopy);
                return;
            }
        } else {
            if (header->func == ENCRYPTED) {
                if (!verify_ECDSA_sig(key.ec, group->hashtype, packet,
                                      meslen, sigcopy, siglen)) {
                    glog1(group, "Signature verification failed");
                    free(sigcopy);
                    return;
                }
            }
            if (!create_ECDSA_sig(group->proxy_privkey.ec, group->hashtype,
                                  packet, meslen, sigcopy, &siglen)) {
                glog0(group, "Signature creation failed");
                free(sigcopy);
                return;
            }
        }
        memcpy(sig, sigcopy, siglen);
        free(sigcopy);
    }

    if (nb_sendto(listener, packet, meslen, 0, (struct sockaddr *)&dest,
               family_len(dest)) == SOCKET_ERROR) {
        gsockerror(group, "Error forwarding message");
        if ((rval = getnameinfo((struct sockaddr *)&dest, family_len(dest),
                destname, sizeof(destname), destport, sizeof(destport),
                NI_NUMERICHOST | NI_NUMERICSERV)) != 0) {
            glog1(group, "getnameinfo failed: %s", gai_strerror(rval));
        }
        glog2(group, "Dest: %s:%s", destname, destport);
    }
    set_timeout(group, 0, 0);
}
Beispiel #23
0
/**
 * Sends back a COMPLETE message in response to a DONE or FILEINFO
 */
void send_complete(struct group_list_t *group, int set_freespace)
{
    unsigned char *buf, *encrypted, *outpacket;
    struct uftp_h *header;
    struct complete_h *complete;
    struct freespace_info_he *freespace;
    int payloadlen, enclen;
    struct timeval tv;

    gettimeofday(&tv, NULL);
    if ((group->phase == PHASE_COMPLETE) &&
            (cmptimestamp(tv, group->expire_time) >= 0)) {
        glog1(group, "Completion unconfirmed by server");
        move_files(group);
        file_cleanup(group, 0);
        return;
    }
    buf = safe_calloc(MAXMTU, 1);

    header = (struct uftp_h *)buf;
    complete = (struct complete_h *)(buf + sizeof(struct uftp_h));
    freespace = (struct freespace_info_he *)((unsigned char *)complete +
                    sizeof(struct complete_h));

    set_uftp_header(header, COMPLETE, group);
    complete->func = COMPLETE;
    if (set_freespace) {
        complete->hlen = (sizeof(struct complete_h) +
                            sizeof(struct freespace_info_he)) / 4;
    } else {
        complete->hlen = sizeof(struct complete_h) / 4;
    }
    complete->status = group->fileinfo.comp_status;
    complete->file_id = htons(group->file_id);
    if (set_freespace) {
        set_freespace_info(group, freespace);
    }

    payloadlen = complete->hlen * 4;
    if ((group->phase != PHASE_REGISTERED) && (group->keytype != KEY_NONE)) {
        encrypted = NULL;
        if (!encrypt_and_sign(buf, &encrypted, payloadlen, &enclen,
                group->keytype, group->groupkey, group->groupsalt,&group->ivctr,
                group->ivlen, group->hashtype, group->grouphmackey,
                group->hmaclen, group->sigtype, group->keyextype,
                group->client_privkey, group->client_privkeylen)) {
            glog0(group, "Error encrypting COMPLETE");
            free(buf);
            return;
        }
        outpacket = encrypted;
        payloadlen = enclen;
    } else {
        encrypted = NULL;
        outpacket = buf;
    }
    payloadlen += sizeof(struct uftp_h);

    if (nb_sendto(listener, outpacket, payloadlen, 0,
               (struct sockaddr *)&group->replyaddr,
               family_len(group->replyaddr)) == SOCKET_ERROR) {
        gsockerror(group, "Error sending COMPLETE");
    } else {
        glog2(group, "COMPLETE sent");
    }
    set_timeout(group, 0);

    free(buf);
    free(encrypted);
}
Beispiel #24
0
/**
 * Forward a message unmodified to the next hop, resigning if necessary.
 */
void forward_message(int listidx, const struct sockaddr_in *src,
                     const unsigned char *packet)
{
    struct uftp_h *header;
    struct encrypted_h *encrypted;
    struct sockaddr_in dest;
    unsigned int meslen, siglen;
    int hostidx;
    uint8_t *sig, *sigcopy;
    RSA_key_t key;

    header = (struct uftp_h *)packet;
    meslen = sizeof(struct uftp_h) + ntohs(header->blsize);

    memset(&dest, 0, sizeof(dest));
    if (!memcmp(src, &group_list[listidx].up_addr, sizeof(*src))) {
        if (proxy_type == RESPONSE_PROXY) {
            // Response proxy, no downstream fowarding
            set_timeout(listidx, 0);
            return;
        } else if (proxy_type == SERVER_PROXY) {
            dest = down_addr;
        } else {
            dest.sin_family = AF_INET;
            dest.sin_addr.s_addr = header->destaddr;
            dest.sin_port = htons(out_port);
            key = group_list[listidx].serverkey;
        }
    } else {
        dest = group_list[listidx].up_addr;
        if (proxy_type != SERVER_PROXY) {
            hostidx = find_client(listidx, header->srcaddr);
            if (hostidx == -1) {
                log(group_list[listidx].group_id, 0,
                        "Couldn't find receiver in list");
                return;
            }
            key = group_list[listidx].destinfo[hostidx].pubkey;
        }
    }

    // If we're using RSA signatures, verify the signature and resign
    if ((proxy_type != SERVER_PROXY) && (header->func == ENCRYPTED) &&
            (group_list[listidx].sigtype == SIG_RSA)) {
        encrypted = (struct encrypted_h *)(packet + sizeof(struct uftp_h));
        sig = (uint8_t *)encrypted + sizeof(struct encrypted_h);
        siglen = ntohs(encrypted->sig_len);

        sigcopy = calloc(siglen, 1);
        if (sigcopy == NULL) {
            syserror(0, 0, "calloc failed!");
            exit(1);
        }
        memcpy(sigcopy, sig, siglen);
        memset(sig, 0, siglen);
        if (!verify_RSA_sig(key, group_list[listidx].hashtype, packet,
                            meslen, sigcopy, siglen)) {
            log(group_list[listidx].group_id, 0,
                    "Signature verification failed");
            free(sigcopy);
            return;
        }
        if (!create_RSA_sig(group_list[listidx].proxykey,
                            group_list[listidx].hashtype, packet, meslen,
                            sigcopy, &siglen)) {
            log(group_list[listidx].group_id, 0,
                    "Signature creation failed");
            free(sigcopy);
            return;
        }
        memcpy(sig, sigcopy, siglen);
        free(sigcopy);
    }

    if (nb_sendto(listener, packet, meslen, 0, (struct sockaddr *)&dest,
               sizeof(struct sockaddr_in)) == SOCKET_ERROR) {
        sockerror(group_list[listidx].group_id, 0, "Error forwarding message");
        log(group_list[listidx].group_id, 0, "Dest: %s:%d",
                inet_ntoa(dest.sin_addr), ntohs(dest.sin_port));
    }
    set_timeout(listidx, 0);
}
Beispiel #25
0
/**
 * Sends a PROXY_KEY message to the first listed public multicast address.
 */
void send_proxy_key()
{
    unsigned char *packet, *keymod, *sig;
    struct uftp_h *header;
    struct proxy_key_h *proxykey;
    uint8_t modulus[PUBKEY_LEN];
    uint32_t exponent, nonce;
    uint16_t modlen;
    unsigned int meslen, siglen;
    struct sockaddr_in pubaddr;

    packet = calloc(sizeof(struct uftp_h) + sizeof(struct hb_req_h) +
                    (PUBKEY_LEN * 2) , 1);
    if (packet == NULL) {
        syserror(0, 0, "calloc failed!");
        exit(1);
    }

    header = (struct uftp_h *)packet;
    proxykey = (struct proxy_key_h *)(packet + sizeof(struct uftp_h));
    keymod = (unsigned char *)proxykey + sizeof(struct proxy_key_h);
    header->uftp_id = UFTP_VER_NUM;
    header->func = PROXY_KEY;
    proxykey->func = PROXY_KEY;

    if (!export_RSA_key(privkey[0], &exponent,
                        modulus, &modlen)) {
        log(0, 0, "Error exporting public key");
        free(packet);
        return;
    }

    nonce = htonl(rand());
    proxykey->nonce = nonce;
    proxykey->keyexp = htonl(exponent);
    memcpy(keymod, modulus, modlen);
    proxykey->keylen = htons(modlen);
    sig = keymod + modlen;
    if (!create_RSA_sig(privkey[0], HASH_SHA1, (unsigned char *)&nonce,
                        sizeof(nonce), sig, &siglen) ||
                siglen > modlen) {
        log(0, 0, "Error signing nonce");
        free(packet);
        return;
    }
    proxykey->siglen = htons(siglen);
    meslen = sizeof(struct proxy_key_h) + modlen + siglen;

    header->blsize = htons(meslen);
    meslen += sizeof(struct uftp_h);
    memset(&pubaddr, 0, sizeof(pubaddr));
    pubaddr.sin_family = AF_INET;
    pubaddr.sin_addr = pub_multi[0];
    pubaddr.sin_port = htons(port);
    if (nb_sendto(listener, packet, meslen, 0, 
                  (struct sockaddr *)&pubaddr,
                  sizeof(struct sockaddr_in)) == SOCKET_ERROR) {
        sockerror(0, 0, "Error sending PROXY_KEY");
    } else {
        log(0, 0, "Sent PROXY_KEY to %s",
                  inet_ntoa(pubaddr.sin_addr));
    }
    free(packet);
}
Beispiel #26
0
/**
 * Sends a CLIENT_KEY message if the server requested it.
 * Always sent right after a REGISTER.
 */
void send_client_key(struct group_list_t *group)
{
    struct uftp_h *header;
    struct client_key_h *client_key;
    unsigned char *buf, *keyblob, *verify;
    uint8_t *verifydata;
    unsigned int siglen, meslen;
    int verifylen;
    uint16_t bloblen;

    buf = safe_calloc(MAXMTU, 1);

    header = (struct uftp_h *)buf;
    client_key = (struct client_key_h *)(buf + sizeof(struct uftp_h));
    keyblob = (unsigned char *)client_key + sizeof(struct client_key_h);

    verifydata = build_verify_data(group, &verifylen);
    if (!verifydata) {
        glog0(group, "Error getting verify data");
        send_abort(group, "Error getting verify data");
        goto end;
    }

    set_uftp_header(header, CLIENT_KEY, group);

    client_key->func = CLIENT_KEY;
    if ((group->keyextype == KEYEX_RSA) ||
            (group->keyextype == KEYEX_ECDH_RSA)) {
        if (!export_RSA_key(group->client_privkey.rsa, keyblob, &bloblen)) {
            glog0(group, "Error exporting public key");
            send_abort(group, "Error exporting public key");
            goto end;
        }
        verify = keyblob + bloblen;
        if (!create_RSA_sig(group->client_privkey.rsa, group->hashtype,
                            verifydata, verifylen, verify, &siglen)) {
            glog0(group, "Error signing verify data");
            send_abort(group, "Error signing verify data");
            goto end;
        }
    } else {
        if (!export_EC_key(group->client_privkey.ec, keyblob, &bloblen)) {
            glog0(group, "Error exporting public key");
            send_abort(group, "Error exporting public key");
            goto end;
        }
        verify = keyblob + bloblen;
        if (!create_ECDSA_sig(group->client_privkey.ec, group->hashtype,
                              verifydata, verifylen, verify, &siglen)) {
            glog0(group, "Error signing verify data");
            send_abort(group, "Error signing verify data");
            goto end;
        }
    }

    client_key->bloblen = htons(bloblen);
    client_key->siglen = htons(siglen);
    client_key->hlen = (sizeof(struct client_key_h) + bloblen + siglen) / 4;

    meslen = sizeof(struct uftp_h) + (client_key->hlen * 4);
    if (nb_sendto(listener, buf, meslen, 0,
               (struct sockaddr *)&(group->replyaddr),
               family_len(group->replyaddr)) == SOCKET_ERROR) {
        gsockerror(group, "Error sending CLIENT_KEY");
    } else {
        glog2(group, "CLIENT_KEY sent");
    }

end:
    free(verifydata);
    free(buf);
}
Beispiel #27
0
/**
 * Sends a KEYINFO to each client that the server sent a REG_CONF for.
 */
void send_keyinfo(struct pr_group_list_t *group, const uint32_t *addrlist,
                  int addrlen)
{
    unsigned char *buf, *iv;
    struct uftp_h *header;
    struct keyinfo_h *keyinfo_hdr;
    struct destkey *keylist;
    unsigned int payloadlen, len;
    int maxdest, packetcnt, dests, iv_init, foundaddr, i, j;
    int unauth_keytype, unauth_keylen, unauth_ivlen;
    struct pr_destinfo_t *dest;

    // Don't use a cipher in an authentication mode to encrypt the group master
    unauth_keytype = unauth_key(group->keytype);
    get_key_info(unauth_keytype, &unauth_keylen, &unauth_ivlen);

    buf = safe_calloc(MAXMTU, 1);
    iv = safe_calloc(unauth_ivlen, 1);
    header = (struct uftp_h *)buf;
    keyinfo_hdr = (struct keyinfo_h *)(buf + sizeof(struct uftp_h));
    keylist= (struct destkey *)((char *)keyinfo_hdr + sizeof(struct keyinfo_h));

    set_uftp_header(header, KEYINFO, group);
    keyinfo_hdr->func = KEYINFO;
    keyinfo_hdr->hlen = sizeof(struct keyinfo_h) / 4;

    iv_init = 0;
    maxdest = max_msg_dest(group, KEYINFO, keyinfo_hdr->hlen * 4);
    packetcnt = 1;
    for (i = 0, dests = 0; i < group->destcount; i++) {
        dest = &group->destinfo[i];
        if (dest->state == PR_CLIENT_CONF) {
            if (addrlist) {
                // We just got a REG_CONF, so only send to listed hosts
                for (j = 0, foundaddr = 0; (j < addrlen) && (!foundaddr); j++) {
                    if (dest->id == addrlist[j]) {
                        foundaddr = 1;
                    }
                }
            } else {
                foundaddr = 1;
            }
            if (foundaddr) {
                if (!iv_init) {
                    group->ivctr++;
                    keyinfo_hdr->iv_ctr_hi =
                            htonl((group->ivctr & 0xFFFFFFFF00000000LL) >> 32);
                    keyinfo_hdr->iv_ctr_lo =
                            htonl(group->ivctr & 0x00000000FFFFFFFFLL);
                    iv_init = 1;
                }
                keylist[dests].dest_id = dest->id;
                build_iv(iv, dest->salt, unauth_ivlen,
                         uftp_htonll(group->ivctr), group->src_id);
                if (!encrypt_block(unauth_keytype, iv, dest->key,
                                   NULL, 0, &group->groupmaster[1],
                                   sizeof(group->groupmaster) - 1,
                                   keylist[dests].groupmaster, &len)) {
                    glog0(group, "Error encrypting KEYINFO for %s", dest->name);
                    free(buf);
                    free(iv);
                    return;
                }
                dests++;
            }
        }
        if ((dests >= maxdest) ||
                ((i == group->destcount - 1) && (dests > 0))) {
            payloadlen = sizeof(struct keyinfo_h) +
                         (dests * sizeof(struct destkey));
            glog2(group,"Sending KEYINFO %d.%d", group->keyinfo_cnt, packetcnt);
            if (nb_sendto(listener, buf, payloadlen + sizeof(struct uftp_h), 0,
                       (struct sockaddr *)&group->privatemcast,
                        family_len(group->privatemcast)) == SOCKET_ERROR) {
                gsockerror(group, "Error sending KEYINFO");
                free(buf);
                free(iv);
                return;
            }
            // TODO: This value is good for around 100Mbps.  This is under the
            // assumption that the client proxy is local to the clients
            // it serves.  This should probably be a parameter.
            usleep(120);
            memset(keylist, 0, maxdest * sizeof(struct destkey));
            iv_init = 0;
            dests = 0;
            packetcnt++;
        }
    }