コード例 #1
0
ファイル: client_announce.c プロジェクト: PumpkinSpace/uftp
/**
 * 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);
}
コード例 #2
0
ファイル: proxy_common.c プロジェクト: fmaker/uftp.deb
/**
 * 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);
}
コード例 #3
0
ファイル: proxy_common.c プロジェクト: PumpkinSpace/uftp
/**
 * 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);
}
コード例 #4
0
ファイル: proxy_common.c プロジェクト: fmaker/uftp.deb
/**
 * 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);
}
コード例 #5
0
ファイル: proxy_common.c プロジェクト: PumpkinSpace/uftp
/**
 * 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);
}