/** * Clean up a group list entry. Free malloc'ed structures, drop the * multicast group (if no one else is using it) and free the slot. */ void group_cleanup(int listidx) { int i; for (i = 0; i < MAX_PEND; i++) { free(group_list[listidx].pending[i].naklist); } if ((group_list[listidx].multi.s_addr != 0) && (proxy_type != CLIENT_PROXY) && !other_mcast_users(listidx) && group_list[listidx].multi_join) { multicast_leave(listener, group_list[listidx].group_id, &group_list[listidx].multi, m_interface, interface_count, server_fp, server_fp_count); } if (group_list[listidx].serverkey) { free_RSA_key(group_list[listidx].serverkey); } for (i = 0; i < group_list[listidx].destcount; i++) { if (group_list[listidx].destinfo[i].pubkey) { free_RSA_key(group_list[listidx].destinfo[i].pubkey); } } memset(&group_list[listidx], 0, sizeof(group_list[listidx])); }
/** * Cleanup routine set up by atexit */ void cleanup(void) { int i, j; closesocket(sock); for (i = 0; i < destcount; i++) { if (keytype != KEY_NONE) { if (destlist[i].encinfo) { if (destlist[i].encinfo->pubkey) { free_RSA_key(destlist[i].encinfo->pubkey); } free(destlist[i].encinfo); } } free(destlist[i].last_status); for (j = 0; j < destlist[i].last_prstatus_cnt; j++) { free(destlist[i].last_prstatus[j]); } if (destlist[i].clients) { free(destlist[i].clients); } } if (keytype != KEY_NONE) { free_RSA_key(privkey); } crypto_cleanup(); #ifdef WINDOWS WSACleanup(); #endif }
/** * Cleanup routine set up by atexit */ void cleanup(void) { int i; for (i = 0; i < MAXLIST; i++) { if (group_list[i].group_id != 0) { group_cleanup(i); } } if (!parent) { for (i = 0; i < pub_multi_count; i++) { multicast_leave(listener, 0, &pub_multi[i], m_interface, interface_count, server_fp, server_fp_count); } } closesocket(listener); for (i = 0; i < key_count; i++) { free_RSA_key(privkey[i]); } crypto_cleanup(); #ifdef WINDOWS WSACleanup(); #endif fclose(stderr); }
/** * Cleanup routine set up by atexit */ void cleanup(void) { int i; closesocket(sock); for (i = 0; i < destcount; i++) { if (keytype != KEY_NONE) { if (destlist[i].encinfo) { if (destlist[i].encinfo->pubkey.key) { if ((keyextype == KEYEX_RSA) || (keyextype == KEYEX_ECDH_RSA)) { free_RSA_key(destlist[i].encinfo->pubkey.rsa); } else { free_EC_key(destlist[i].encinfo->pubkey.ec); } if ((keyextype == KEYEX_ECDH_RSA) || (keyextype == KEYEX_ECDH_ECDSA)) { free_EC_key(destlist[i].encinfo->dhkey.ec); } } free(destlist[i].encinfo); } } } if (keytype != KEY_NONE) { if ((keyextype == KEYEX_RSA) || (keyextype == KEYEX_ECDH_RSA)) { free_RSA_key(privkey.rsa); } else { free_EC_key(privkey.ec); } if ((keyextype == KEYEX_ECDH_RSA) || (keyextype == KEYEX_ECDH_ECDSA)) { free_EC_key(dhkey.ec); } } crypto_cleanup(); if (status_file) { fclose(status_file); } #ifdef WINDOWS WSACleanup(); #endif }
/** * Clean up a group list entry. Free malloc'ed structures, drop the * multicast group (if no one else is using it) and free the slot. */ void group_cleanup(struct pr_group_list_t *group) { int i; for (i = 0; i < MAX_PEND; i++) { free(group->pending[i].naklist); } if (!addr_blank(&group->privatemcast) && (proxy_type != CLIENT_PROXY) && !other_mcast_users(group) && group->multi_join) { multicast_leave(listener, group->group_id, &group->privatemcast, m_interface, interface_count, server_fp, server_fp_count); } if (group->server_pubkey.key) { if ((group->keyextype == KEYEX_RSA) || (group->keyextype == KEYEX_ECDH_RSA)) { free_RSA_key(group->server_pubkey.rsa); } else { free_EC_key(group->server_pubkey.ec); } if ((group->keyextype == KEYEX_ECDH_RSA) || (group->keyextype == KEYEX_ECDH_ECDSA)) { free_EC_key(group->server_dhkey.ec); free_EC_key(group->proxy_dhkey.ec); } } for (i = 0; i < group->destcount; i++) { if (group->destinfo[i].pubkey.key) { if ((group->keyextype == KEYEX_RSA) || (group->keyextype == KEYEX_ECDH_RSA)) { free_RSA_key(group->destinfo[i].pubkey.rsa); } else { free_EC_key(group->destinfo[i].pubkey.ec); } if ((group->keyextype == KEYEX_ECDH_RSA) || (group->keyextype == KEYEX_ECDH_ECDSA)) { free_EC_key(group->destinfo[i].dhkey.ec); } } } memset(group, 0, sizeof(struct pr_group_list_t)); }
/** * Cleanup routine set up by atexit */ void cleanup(void) { int i; for (i = 0; i < MAXLIST; i++) { if (group_list[i].group_id != 0) { send_abort(&group_list[i], "Client shutting down"); file_cleanup(&group_list[i], 1); } } if (!parent) { for (i = 0; i < pub_multi_count; i++) { if (server_count > 0) { multicast_leave(listener, 0, &pub_multi[i], m_interface, interface_count, server_keys, server_count); if (has_proxy) { multicast_leave(listener, 0, &pub_multi[i], m_interface, interface_count, &proxy_info, 1); } } else { multicast_leave(listener, 0, &pub_multi[i], m_interface, interface_count, NULL, 0); } } } closesocket(listener); for (i = 0; i < key_count; i++) { if (privkey_type[i] == KEYBLOB_RSA) { free_RSA_key(privkey[i].rsa); } else { free_EC_key(privkey[i].ec); } } crypto_cleanup(); #ifdef WINDOWS WSACleanup(); #endif close_log(); }
/** * Cleanup routine set up by atexit */ void cleanup(void) { int i; for (i = 0; i < MAXLIST; i++) { if (group_list[i].group_id != 0) { file_cleanup(i, 1); } } if (!parent) { for (i = 0; i < pub_multi_count; i++) { if (server_count > 0) { multicast_leave(listener, 0, &pub_multi[i], m_interface, interface_count, server_keys, server_count); if (has_proxy) { multicast_leave(listener, 0, &pub_multi[i], m_interface, interface_count, &proxy_info, 1); } } else { multicast_leave(listener, 0, &pub_multi[i], m_interface, interface_count, NULL, 0); } } } closesocket(listener); for (i = 0; i < key_count; i++) { free_RSA_key(privkey[i]); } crypto_cleanup(); #ifdef WINDOWS WSACleanup(); #endif fclose(stderr); }
/** * Clean up a group list entry. Close the file if open, * free malloc'ed structures, drop the multicast group * (if no one else is using it) and free the slot. */ void file_cleanup(int listidx, int abort) { if (group_list[listidx].fileinfo.fd >= 0) { close(group_list[listidx].fileinfo.fd); group_list[listidx].fileinfo.fd = -1; if (tempfile) { move_to_backup(listidx); if (rename(group_list[listidx].fileinfo.temppath, group_list[listidx].fileinfo.filepath) == -1) { syserror(group_list[listidx].group_id, group_list[listidx].file_id, "Couldn't rename from %s to %s", group_list[listidx].fileinfo.temppath, group_list[listidx].fileinfo.filepath); } } if (group_list[listidx].fileinfo.tstamp) { utim_buf utbuf; utbuf.actime = group_list[listidx].fileinfo.tstamp; utbuf.modtime = group_list[listidx].fileinfo.tstamp; if (utime(group_list[listidx].fileinfo.filepath, &utbuf) == -1) { syserror(group_list[listidx].group_id, group_list[listidx].file_id, "utime failed"); } } } if ((group_list[listidx].version == UFTP_V2_VER) || abort || (group_list[listidx].file_id == 0)) { if ((group_list[listidx].multi.s_addr != 0) && !other_mcast_users(listidx) && group_list[listidx].multi_join) { if (server_count > 0) { multicast_leave(listener, group_list[listidx].group_id, &group_list[listidx].multi, m_interface, interface_count, server_keys, server_count); if (has_proxy) { multicast_leave(listener, group_list[listidx].group_id, &group_list[listidx].multi, m_interface, interface_count, &proxy_info, 1); } } else { multicast_leave(listener, group_list[listidx].group_id, &group_list[listidx].multi, m_interface, interface_count, NULL, 0); } } if (group_list[listidx].serverkey) { free_RSA_key(group_list[listidx].serverkey); } if (group_list[listidx].restartinfo && (strcmp(group_list[listidx].restartinfo->name, ""))) { // We have unused restart info from the last run. // Chalk this up as a loss and delete the data file char filepath[MAXPATHNAME]; snprintf(filepath, sizeof(filepath), "%s%c_group_%08X%c%s", tempdir, PATH_SEP, group_list[listidx].group_id, PATH_SEP, group_list[listidx].restartinfo->name); unlink(filepath); } if (abort) { write_restart_file(listidx); } free(group_list[listidx].fileinfo.naklist); free(group_list[listidx].fileinfo.section_done); if (group_list[listidx].restartinfo) { free(group_list[listidx].restartinfo->naklist); free(group_list[listidx].restartinfo->section_done); free(group_list[listidx].restartinfo); } memset(&group_list[listidx], 0, sizeof(group_list[listidx])); } else { // Don't clear the file_id in case we need to respond to late DONEs group_list[listidx].phase = PHASE_MIDGROUP; set_timeout(listidx); free(group_list[listidx].fileinfo.naklist); free(group_list[listidx].fileinfo.section_done); group_list[listidx].fileinfo.naklist = NULL; group_list[listidx].fileinfo.section_done = NULL; } }
/** * 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; } } }
/** * Clean up a group list entry. Close the file if open, * free malloc'ed structures, drop the multicast group * (if no one else is using it) and free the slot. */ void file_cleanup(struct group_list_t *group, int abort_session) { if (group->fileinfo.fd >= 0) { glog2(group, "starting file close"); close(group->fileinfo.fd); glog2(group, "done file close"); group->fileinfo.fd = -1; if (abort_session && !strcmp(tempdir, "")) { if (tempfile) { unlink(group->fileinfo.temppath); } else { unlink(group->fileinfo.filepath); } } else { if (tempfile) { move_to_backup(group); if (rename(group->fileinfo.temppath, group->fileinfo.filepath) == -1) { gsyserror(group, "Couldn't rename from %s to %s", group->fileinfo.temppath,group->fileinfo.filepath); } } if (group->fileinfo.tstamp) { utim_buf utbuf; utbuf.actime = group->fileinfo.tstamp; utbuf.modtime = group->fileinfo.tstamp; if (utime(group->fileinfo.filepath, &utbuf) == -1) { gsyserror(group, "utime failed"); } } } } if (abort_session || (group->file_id == 0)) { if (!addr_blank(&group->multi) && !other_mcast_users(group) && group->multi_join) { if (server_count > 0) { multicast_leave(listener, group->group_id, &group->multi, m_interface, interface_count, server_keys,server_count); if (has_proxy) { multicast_leave(listener, group->group_id, &group->multi, m_interface, interface_count, &proxy_info, 1); } } else { multicast_leave(listener, group->group_id, &group->multi, m_interface, interface_count, NULL, 0); } } if (group->server_pubkey.key) { if (group->keyextype == KEYEX_ECDH_ECDSA) { free_EC_key(group->server_pubkey.ec); } else { free_RSA_key(group->server_pubkey.rsa); } } if (group->server_dhkey.key) { free_EC_key(group->server_dhkey.ec); free_EC_key(group->client_dhkey.ec); } if (group->restartinfo && (strcmp(group->restartinfo->name, ""))) { // We have unused restart info from the last run. // Chalk this up as a loss and delete the data file char filepath[MAXPATHNAME]; snprintf(filepath, sizeof(filepath), "%s%c_group_%08X%c%s", tempdir, PATH_SEP, group->group_id, PATH_SEP, group->restartinfo->name); unlink(filepath); } if (abort_session) { write_restart_file(group); } free(group->loss_history); free(group->fileinfo.naklist); free(group->fileinfo.section_done); free(group->fileinfo.cache); free(group->fileinfo.cache_status); if (group->restartinfo) { free(group->restartinfo->naklist); free(group->restartinfo->section_done); free(group->restartinfo); } memset(group, 0, sizeof(struct group_list_t)); } else { // Don't clear the file_id in case we need to respond to late DONEs if (!strcmp(tempdir, "")) { run_postreceive(group, group->fileinfo.filepath); } group->phase = PHASE_MIDGROUP; set_timeout(group, 0); free(group->fileinfo.naklist); free(group->fileinfo.section_done); free(group->fileinfo.cache); free(group->fileinfo.cache_status); group->fileinfo.naklist = NULL; group->fileinfo.section_done = NULL; group->fileinfo.cache = NULL; group->fileinfo.cache_status = NULL; } }