/** * Verifies the data in a CLIENT_KEY message signed by the client's public key */ int verify_client_key(struct pr_group_list_t *group, int hostidx) { uint8_t *verifydata; int verifylen; struct pr_destinfo_t *dest; dest = &group->destinfo[hostidx]; // build_verify_data should never fail in this case verifydata = build_verify_data(group, hostidx, &verifylen, 0); if ((group->keyextype == KEYEX_RSA) || (group->keyextype == KEYEX_ECDH_RSA)) { if (!verify_RSA_sig(dest->pubkey.rsa, group->hashtype, verifydata, verifylen, dest->verifydata, dest->verifylen)) { glog1(group, "Rejecting CLIENT_KEY from %s: verify data mismatch", dest->name); free(verifydata); return 0; } } else { if (!verify_ECDSA_sig(dest->pubkey.ec, group->hashtype, verifydata, verifylen, dest->verifydata, dest->verifylen)) { glog1(group, "Rejecting CLIENT_KEY from %s: verify data mismatch", dest->name); free(verifydata); return 0; } } free(verifydata); return 1; }
/** * Process a PROXY_KEY message */ void handle_proxy_key(const struct sockaddr_in *src, const unsigned char *message) { struct uftp_h *header; struct proxy_key_h *proxykey; unsigned char *keymod, *sig; struct hostent *hp; RSA_key_t key; unsigned char *verifydata, fingerprint[HMAC_LEN]; unsigned int verifylen, fplen, keylen, siglen; header = (struct uftp_h *)message; proxykey = (struct proxy_key_h *)(message + sizeof(struct uftp_h)); if (!noname && (hp = gethostbyaddr((char *)&src->sin_addr, sizeof(struct in_addr), AF_INET))) { log(0, 0, "Received PROXY_KEY from %s (%s)", hp->h_name, inet_ntoa(src->sin_addr)); } else { log(0, 0, "Received PROXY_KEY from %s", inet_ntoa(src->sin_addr)); } if (!has_proxy) { log(0, 0, "No reply proxy specified"); return; } if ((src->sin_addr.s_addr != proxy_info.addr.s_addr) || (src->sin_port != htons(port))) { log(0, 0, "PROXY_KEY not from specified reply proxy"); return; } keymod = (unsigned char *)proxykey + sizeof(struct proxy_key_h); keylen = ntohs(proxykey->keylen); sig = keymod + keylen; siglen = ntohs(proxykey->siglen); // First check key fingerprint if (proxy_info.has_fingerprint) { verifylen = 0; verifydata = calloc(sizeof(proxykey->keyexp) + keylen, 1); if (verifydata == NULL) { syserror(0, 0, "calloc failed!"); exit(1); } memcpy(verifydata, &proxykey->keyexp, sizeof(proxykey->keyexp)); verifylen += sizeof(proxykey->keyexp); memcpy(verifydata + verifylen, keymod, keylen); verifylen += keylen; hash(HASH_SHA1, verifydata, verifylen, fingerprint, &fplen); if (memcmp(proxy_info.fingerprint, fingerprint, fplen)) { log0(0, 0, "Failed to verify PROXY_KEY fingerprint"); free(verifydata); return; } free(verifydata); } // Then check signature if (!import_RSA_key(&key, ntohl(proxykey->keyexp), keymod, keylen)) { log0(0, 0, "Failed to import public key from PROXY_KEY"); return; } if (!verify_RSA_sig(key, HASH_SHA1, (unsigned char *)&proxykey->nonce, sizeof(proxykey->nonce), sig, siglen)) { log0(0, 0, "Failed to verify PROXY_KEY signature"); return; } // Load key if (!import_RSA_key(&proxy_key, ntohl(proxykey->keyexp), keymod, keylen)) { log0(0, 0, "Failed to import public key from PROXY_KEY"); return; } }
/** * Read encryption related fields from an ANNOUNCE */ int read_announce_encryption(struct group_list_t *group, struct enc_info_he *encinfo, const unsigned char *packet, int packetlen) { int keyextype, sigtype, keytype, i; unsigned char *keys; keys = (unsigned char *)encinfo + sizeof(struct enc_info_he); // Sanity check the selected encryption parameters if (!cipher_supported(encinfo->keytype)) { glog1(group, "Keytype invalid or not supported here"); send_abort(group, "Keytype invalid or not supported here"); return 0; } if (!hash_supported(encinfo->hashtype)) { glog1(group, "Hashtype invalid or not supported here"); send_abort(group, "Hashtype invalid or not supported here"); return 0; } keyextype = (encinfo->keyextype_sigtype & 0xF0) >> 4; sigtype = encinfo->keyextype_sigtype & 0x0F; if (((sigtype != SIG_HMAC) && (sigtype != SIG_KEYEX) && (sigtype != SIG_AUTHENC)) || ((sigtype == SIG_AUTHENC) && (!is_auth_enc(encinfo->keytype)))) { glog1(group, "Invalid sigtype specified"); send_abort(group, "Invalid sigtype specified"); return 0; } if ((keyextype != KEYEX_RSA) && (keyextype != KEYEX_ECDH_RSA) && (keyextype != KEYEX_ECDH_ECDSA)) { glog1(group, "Invalid keyextype specified"); send_abort(group, "Invalid keyextype specified"); return 0; } group->keyextype = keyextype; group->keytype = encinfo->keytype; group->hashtype = encinfo->hashtype; group->sigtype = sigtype; group->client_auth = ((encinfo->flags & FLAG_CLIENT_AUTH) != 0); if (!verify_server_fingerprint(keys, ntohs(encinfo->keylen), group)) { glog1(group, "Failed to verify server key fingerprint"); send_abort(group, "Failed to verify server key fingerprint"); return 0; } if ((group->keyextype == KEYEX_RSA) || (group->keyextype == KEYEX_ECDH_RSA)) { keytype = KEYBLOB_RSA; } else { keytype = KEYBLOB_EC; } // Load server key and select a matching client key if (keytype == KEYBLOB_RSA) { if (!import_RSA_key(&group->server_pubkey.rsa, keys, ntohs(encinfo->keylen))) { glog0(group, "Failed to load server public key"); send_abort(group, "Failed to load server public key"); return 0; } group->server_pubkeylen = RSA_keylen(group->server_pubkey.rsa); for (i = 0; i < key_count; i++) { if ((privkey_type[i] == KEYBLOB_RSA) && (group->server_pubkeylen == RSA_keylen(privkey[i].rsa))) { group->client_privkey = privkey[i]; group->client_privkeylen = RSA_keylen(privkey[i].rsa); break; } } } else { if (!import_EC_key(&group->server_pubkey.ec, keys, ntohs(encinfo->keylen), 0)) { glog0(group, "Failed to load server public key"); send_abort(group, "Failed to load server public key"); return 0; } group->server_pubkeylen = ECDSA_siglen(group->server_pubkey.ec); for (i = 0; i < key_count; i++) { if ((privkey_type[i] == KEYBLOB_EC) && (get_EC_curve(group->server_pubkey.ec) == get_EC_curve(privkey[i].ec))) { group->client_privkey = privkey[i]; group->client_privkeylen = ECDSA_siglen(privkey[i].ec); break; } } } if (!group->client_privkey.key) { glog1(group, "No client key compatible with server key"); send_abort(group, "No client key compatible with server key"); return 0; } if (has_proxy) { if (!proxy_pubkey.key) { glog1(group, "Response proxy set but haven't gotten key yet"); send_abort(group,"Response proxy set but haven't gotten key yet"); return 0; } if (!(((keytype == KEYBLOB_RSA) && (proxy_pubkeytype == KEYBLOB_RSA)) && (RSA_keylen(group->server_pubkey.rsa) == RSA_keylen(proxy_pubkey.rsa))) && !(((keytype == KEYBLOB_EC) && (proxy_pubkeytype==KEYBLOB_EC)) && (get_EC_curve(group->server_pubkey.ec) == get_EC_curve(proxy_pubkey.ec)))) { glog1(group, "Response proxy key not compatible with server key"); send_abort(group, "Response proxy key not compatible with server key"); return 0; } } if ((group->keyextype == KEYEX_ECDH_ECDSA) || (group->keyextype == KEYEX_ECDH_RSA)) { unsigned char *sigcopy; int siglen; unsigned char *dhblob = keys + ntohs(encinfo->keylen); unsigned char *sig = dhblob + ntohs(encinfo->dhlen); if (!import_EC_key(&group->server_dhkey.ec, dhblob, ntohs(encinfo->dhlen), 1)) { glog0(group, "Failed to load server public ECDH key"); send_abort(group, "Failed to load server public ECDH key"); return 0; } group->client_dhkey.ec = gen_EC_key(get_EC_curve(group->server_dhkey.ec), 1, NULL); if (!group->client_dhkey.key) { glog0(group, "Failed to generate client ECDH key"); send_abort(group, "Failed to generate client ECDH key"); return 0; } if (has_proxy) { // We already checked if the proxy key exists, so no need to repeat if (get_EC_curve(group->server_dhkey.ec) != get_EC_curve(proxy_dhkey.ec)) { glog1(group, "Response proxy ECDH key " "not compatible with server ECDH key"); send_abort(group, "Response proxy ECDH key " "not compatible with server ECDH key"); return 0; } } siglen = ntohs(encinfo->siglen); sigcopy = safe_calloc(siglen, 1); memcpy(sigcopy, sig, siglen); memset(sig, 0, siglen); if (keytype == KEYBLOB_RSA) { if (!verify_RSA_sig(group->server_pubkey.rsa, group->hashtype, packet, packetlen, sigcopy, siglen)) { glog1(group, "Signature verification failed"); send_abort(group, "Signature verification failed"); free(sigcopy); return 0; } } else { if (!verify_ECDSA_sig(group->server_pubkey.ec, group->hashtype, packet, packetlen, sigcopy, siglen)) { glog1(group, "Signature verification failed"); send_abort(group, "Signature verification failed"); free(sigcopy); return 0; } } free(sigcopy); } // Calculate keys if (!calculate_server_keys(group, encinfo)) { return 0; } return 1; }
/** * 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); }
/** * 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); }
/** * Process a PROXY_KEY message */ void handle_proxy_key(const union sockaddr_u *src, unsigned char *message, unsigned meslen) { struct proxy_key_h *proxykey; unsigned char *keyblob, *dhblob, *sig; unsigned char fingerprint[HMAC_LEN]; unsigned int fplen, keylen, dhlen, siglen; char addrname[INET6_ADDRSTRLEN]; int rval; proxykey = (struct proxy_key_h *)message; if (meslen < (proxykey->hlen * 4U) || ((proxykey->hlen * 4U) < sizeof(struct proxy_key_h) + ntohs(proxykey->bloblen) + ntohs(proxykey->dhlen) + ntohs(proxykey->siglen))) { log2(0, 0, 0, "Rejecting PROXY_KEY: invalid message size"); return; } if ((rval = getnameinfo((const struct sockaddr *)src, family_len(*src), addrname, sizeof(addrname), NULL, 0, NI_NUMERICHOST)) != 0) { log1(0, 0, 0, "getnameinfo failed: %s", gai_strerror(rval)); } log2(0, 0, 0, "Received PROXY_KEY from %s", addrname); if (!has_proxy) { log2(0, 0, 0, "No reply proxy specified"); return; } if (!addr_equal(&proxy_info.addr, src)) { log2(0, 0, 0, "PROXY_KEY not from specified reply proxy"); return; } keyblob = (unsigned char *)proxykey + sizeof(struct proxy_key_h); keylen = ntohs(proxykey->bloblen); dhblob = keyblob + keylen; dhlen = ntohs(proxykey->dhlen); sig = dhblob + dhlen; siglen = ntohs(proxykey->siglen); if (keyblob[0] == KEYBLOB_RSA) { if (!import_RSA_key(&proxy_pubkey.rsa, keyblob, keylen)) { log0(0, 0, 0, "Failed to import public key from PROXY_KEY"); return; } if (proxy_info.has_fingerprint) { hash(HASH_SHA1, keyblob, keylen, fingerprint, &fplen); if (memcmp(proxy_info.fingerprint, fingerprint, fplen)) { log1(0, 0, 0, "Failed to verify PROXY_KEY fingerprint"); free_RSA_key(proxy_pubkey.rsa); return; } } if (!verify_RSA_sig(proxy_pubkey.rsa, HASH_SHA1, (unsigned char *)&proxykey->nonce, sizeof(proxykey->nonce), sig, siglen)) { log1(0, 0, 0, "Failed to verify PROXY_KEY signature"); free_RSA_key(proxy_pubkey.rsa); return; } } else { if (!import_EC_key(&proxy_pubkey.ec, keyblob, keylen, 0)) { log0(0, 0, 0, "Failed to import public key from PROXY_KEY"); return; } if (proxy_info.has_fingerprint) { hash(HASH_SHA1, keyblob, keylen, fingerprint, &fplen); if (memcmp(proxy_info.fingerprint, fingerprint, fplen)) { log1(0, 0, 0, "Failed to verify PROXY_KEY fingerprint"); free_RSA_key(proxy_pubkey.rsa); return; } } if (!verify_ECDSA_sig(proxy_pubkey.ec, HASH_SHA1, (unsigned char *)&proxykey->nonce, sizeof(proxykey->nonce), sig, siglen)) { log1(0, 0, 0, "Failed to verify PROXY_KEY signature"); free_RSA_key(proxy_pubkey.rsa); return; } } if (dhlen) { if (!import_EC_key(&proxy_dhkey.ec, dhblob, dhlen, 1)) { log0(0, 0, 0, "Failed to import ECDH public key from PROXY_KEY"); return; } } }
/** * 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); }
/** * 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); }