Exemple #1
0
/**
 * Process an HB_REQ message
 */
void handle_hb_request(const struct sockaddr_in *src,
                       const unsigned char *packet)
{
    struct uftp_h *header;
    struct hb_req_h *hbreq;
    unsigned char *keymod, *sig;
    struct hostent *hp;
    RSA_key_t key;
    unsigned char *verifydata, fingerprint[HMAC_LEN];
    unsigned int verifylen, fplen, keylen, siglen;
    int resp;

    header = (struct uftp_h *)packet;
    hbreq = (struct hb_req_h *)(packet + sizeof(struct uftp_h));

    if (!noname && (hp = gethostbyaddr((char *)&src->sin_addr,
                                       sizeof(struct in_addr), AF_INET))) {
        log(0, 0, "Received HB_REQ from %s (%s)",
                  hp->h_name, inet_ntoa(src->sin_addr));
    } else {
        log(0, 0, "Received HB_REQ from %s", inet_ntoa(src->sin_addr));
    }
    if ((proxy_type == SERVER_PROXY) && have_down_fingerprint) {
        if ((down_addr.sin_addr.s_addr == src->sin_addr.s_addr) &&
                down_addr.sin_port == src->sin_port) {
            resp = HB_AUTH_OK;
        } else if (down_nonce != ntohl(hbreq->nonce)) {
            resp = HB_AUTH_CHALLENGE;
        } else {
            keymod = (unsigned char *)hbreq + sizeof(struct hb_req_h);
            keylen = ntohs(hbreq->keylen);
            sig = keymod + keylen;
            siglen = ntohs(hbreq->siglen);

            // First check key fingerprint
            verifylen = 0;
            verifydata = calloc(sizeof(hbreq->keyexp) + keylen, 1);
            if (verifydata == NULL) {
                syserror(0, 0, "calloc failed!");
                exit(1);
            }
            memcpy(verifydata, &hbreq->keyexp, sizeof(hbreq->keyexp));
            verifylen += sizeof(hbreq->keyexp);
            memcpy(verifydata + verifylen, keymod, keylen);
            verifylen += keylen;
            hash(HASH_SHA1, verifydata, verifylen, fingerprint, &fplen);
            if (memcmp(down_fingerprint, fingerprint, fplen)) {
                log(0, 0, "Failed to verify HB_REQ fingerprint");
                free(verifydata);
                resp = HB_AUTH_FAILED;
                goto end;
            }
            free(verifydata);

            // Then check signature
            if (!import_RSA_key(&key, ntohl(hbreq->keyexp), keymod, keylen)) {
                log(0, 0, "Failed to import public key from HB_REQ");
                resp = HB_AUTH_FAILED;
                goto end;
            } 

            if (!verify_RSA_sig(key, HASH_SHA1, (unsigned char *)&hbreq->nonce,
                    sizeof(hbreq->nonce), sig, siglen)) {
                log(0, 0, "Failed to verify HB_REQ signature");
                resp = HB_AUTH_FAILED;
                goto end;
            }

            down_addr = *src;
            log(0, 0, "Using %s:%d as downstream address:port",
                      inet_ntoa(src->sin_addr), ntohs(src->sin_port));
            down_nonce = rand();
            resp = HB_AUTH_OK;
        }
    } else {
        resp = HB_AUTH_OK;
    }

end:
    send_hb_response(src, resp);
}
Exemple #2
0
/**
 * Process an HB_REQ message
 */
void handle_hb_request(const union sockaddr_u *src,
                       unsigned char *packet, unsigned packetlen)
{
    struct hb_req_h *hbreq;
    unsigned char *keyblob, *sig;
    union key_t key;
    unsigned char fingerprint[HMAC_LEN];
    unsigned int fplen, bloblen, siglen;
    char destname[INET6_ADDRSTRLEN], destport[PORTNAME_LEN];
    int resp, rval;

    hbreq = (struct hb_req_h *)(packet + sizeof(struct uftp_h));

    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));
    }
    if ((packetlen < sizeof(struct uftp_h) + (hbreq->hlen * 4)) ||
            ((hbreq->hlen * 4) < sizeof(struct hb_req_h))) {
        log1(0,0,0, "Rejecting HB_REQ from %s: invalid message size", destname);
        return;
    }
    log2(0, 0, 0, "Received HB_REQ from %s", destname);
    if ((proxy_type == SERVER_PROXY) && have_down_fingerprint) {
        if (addr_equal(&down_addr, src)) {
            resp = HB_AUTH_OK;
        } else if (down_nonce != ntohl(hbreq->nonce)) {
            resp = HB_AUTH_CHALLENGE;
        } else {
            keyblob = (unsigned char *)hbreq + sizeof(struct hb_req_h);
            bloblen = ntohs(hbreq->bloblen);
            sig = keyblob + bloblen;
            siglen = ntohs(hbreq->siglen);

            // First check key fingerprint, then check signature
            if (keyblob[0] == KEYBLOB_RSA) {
                if (!import_RSA_key(&key.rsa, keyblob, bloblen)) {
                    log1(0, 0, 0, "Failed to import public key from HB_REQ");
                    resp = HB_AUTH_FAILED;
                    goto end;
                } 

                hash(HASH_SHA1, keyblob, bloblen, fingerprint, &fplen);
                if (memcmp(down_fingerprint, fingerprint, fplen)) {
                    log1(0, 0, 0, "Failed to verify HB_REQ fingerprint");
                    resp = HB_AUTH_FAILED;
                    goto end;
                }

                if (!verify_RSA_sig(key.rsa, HASH_SHA1,
                        (unsigned char *)&hbreq->nonce,
                        sizeof(hbreq->nonce), sig, siglen)) {
                    log1(0, 0, 0, "Failed to verify HB_REQ signature");
                    resp = HB_AUTH_FAILED;
                    goto end;
                }
            } else {
                if (!import_EC_key(&key.ec, keyblob, bloblen, 0)) {
                    log1(0, 0, 0, "Failed to import public key from HB_REQ");
                    resp = HB_AUTH_FAILED;
                    goto end;
                } 

                hash(HASH_SHA1, keyblob, bloblen, fingerprint, &fplen);
                if (memcmp(down_fingerprint, fingerprint, fplen)) {
                    log1(0, 0, 0, "Failed to verify HB_REQ fingerprint");
                    resp = HB_AUTH_FAILED;
                    goto end;
                }

                if (!verify_ECDSA_sig(key.ec, HASH_SHA1,
                        (unsigned char *)&hbreq->nonce,
                        sizeof(hbreq->nonce), sig, siglen)) {
                    log1(0, 0, 0, "Failed to verify HB_REQ signature");
                    resp = HB_AUTH_FAILED;
                    goto end;
                }
            }

            down_addr = *src;
            log2(0, 0, 0, "Using %s:%s as downstream address:port",
                       destname, destport);
            down_nonce = rand32();
            resp = HB_AUTH_OK;
        }
    } else {
        resp = HB_AUTH_OK;
    }

end:
    send_hb_response(src, resp);
}