static void psync_notifications_download_thumb(const binresult *thumb, const char *thumbpath){ const char *path, *filename, *host; char *filepath, *tmpfilepath, *buff; char cookie[128]; psync_http_socket *sock; psync_stat_t st; psync_file_t fd; int rd; rd=-1; path=psync_find_result(thumb, "path", PARAM_STR)->str; filename=strrchr(path, '/'); if (unlikely_log(!filename++)) return; filepath=psync_strcat(thumbpath, PSYNC_DIRECTORY_SEPARATOR, filename, NULL); if (!psync_stat(filepath, &st)){ debug(D_NOTICE, "skipping download of %s as it already exists", filename); goto err0; } tmpfilepath=psync_strcat(filepath, ".part", NULL); debug(D_NOTICE, "downloading thumbnail %s", filename); if (unlikely_log((fd=psync_file_open(tmpfilepath, P_O_WRONLY, P_O_CREAT|P_O_TRUNC))==INVALID_HANDLE_VALUE)) goto err1; sock=psync_http_connect_multihost(psync_find_result(thumb, "hosts", PARAM_ARRAY), &host); if (unlikely_log(!sock)) goto err2; psync_slprintf(cookie, sizeof(cookie), "Cookie: dwltag=%s\015\012", psync_find_result(thumb, "dwltag", PARAM_STR)->str); if (unlikely_log(psync_http_request(sock, host, path, 0, 0, cookie))) goto err3; if (unlikely_log(psync_http_next_request(sock))) goto err3; buff=(char *)psync_malloc(PSYNC_COPY_BUFFER_SIZE); while (1){ rd=psync_http_request_readall(sock, buff, PSYNC_COPY_BUFFER_SIZE); if (rd<=0) break; if (psync_file_write(fd, buff, rd)!=rd) break; } psync_free(buff); err3: psync_http_close(sock); err2: psync_file_close(fd); err1: if (rd==0 && !psync_file_rename_overwrite(tmpfilepath, filepath)) debug(D_NOTICE, "downloaded thumbnail %s", filename); else debug(D_WARNING, "downloading of thumbnail %s failed", filename); psync_free(tmpfilepath); err0: psync_free(filepath); }
static int psync_p2p_download(psync_socket_t sock, psync_fileid_t fileid, const unsigned char *filehashhex, uint64_t fsize, const char *filename){ uint32_t keylen, enctype; psync_symmetric_key_t key; psync_encrypted_symmetric_key_t ekey; psync_crypto_aes256_ctr_encoder_decoder_t decoder; psync_hash_ctx hashctx; uint64_t off; size_t rd; psync_file_t fd; unsigned char buff[4096]; unsigned char hashbin[PSYNC_HASH_DIGEST_LEN], hashhex[PSYNC_HASH_DIGEST_HEXLEN]; if (unlikely_log(socket_read_all(sock, &keylen, sizeof(keylen)) || socket_read_all(sock, &enctype, sizeof(enctype)))) return PSYNC_NET_TEMPFAIL; if (enctype!=P2P_ENCTYPE_RSA_AES){ debug(D_ERROR, "unknown encryption type %u", (unsigned)enctype); return PSYNC_NET_PERMFAIL; } if (keylen>PSYNC_P2P_RSA_SIZE/8*2){ /* PSYNC_P2P_RSA_SIZE/8 is enough actually */ debug(D_ERROR, "too long key - %u bytes", (unsigned)keylen); return PSYNC_NET_PERMFAIL; } ekey=psync_ssl_alloc_encrypted_symmetric_key(keylen); if (unlikely_log(socket_read_all(sock, ekey->data, keylen)) || unlikely_log((key=psync_ssl_rsa_decrypt_symmetric_key(psync_rsa_private, ekey))==PSYNC_INVALID_SYM_KEY)){ psync_free(ekey); return PSYNC_NET_TEMPFAIL; } psync_free(ekey); decoder=psync_crypto_aes256_ctr_encoder_decoder_create(key); psync_ssl_free_symmetric_key(key); if (decoder==PSYNC_CRYPTO_INVALID_ENCODER) return PSYNC_NET_PERMFAIL; fd=psync_file_open(filename, P_O_WRONLY, P_O_CREAT|P_O_TRUNC); if (unlikely(fd==INVALID_HANDLE_VALUE)){ psync_crypto_aes256_ctr_encoder_decoder_free(decoder); debug(D_ERROR, "could not open %s", filename); return PSYNC_NET_PERMFAIL; } off=0; psync_hash_init(&hashctx); while (off<fsize){ if (fsize-off>sizeof(buff)) rd=sizeof(buff); else rd=fsize-off; if (unlikely_log(socket_read_all(sock, buff, rd))) goto err0; psync_crypto_aes256_ctr_encode_decode_inplace(decoder, buff, rd, off); if (unlikely_log(psync_file_write(fd, buff, rd)!=rd)) goto err0; psync_hash_update(&hashctx, buff, rd); off+=rd; } psync_crypto_aes256_ctr_encoder_decoder_free(decoder); psync_file_close(fd); psync_hash_final(hashbin, &hashctx); psync_binhex(hashhex, hashbin, PSYNC_HASH_DIGEST_LEN); debug(D_NOTICE, "downloaded file %s from peer", filename); if (memcmp(hashhex, filehashhex, PSYNC_HASH_DIGEST_HEXLEN)){ /* it is better to return permanent fail and let the block checksum algo to find bad blocks */ debug(D_WARNING, "got bad checksum for file %s", filename); return PSYNC_NET_PERMFAIL; } else return PSYNC_NET_OK; err0: psync_crypto_aes256_ctr_encoder_decoder_free(decoder); psync_file_close(fd); psync_hash_final(hashbin, &hashctx); return PSYNC_NET_TEMPFAIL; }
static void psync_p2p_tcphandler(void *ptr){ packet_get packet; psync_fileid_t localfileid; psync_binary_rsa_key_t binpubrsa; psync_rsa_publickey_t pubrsa; psync_symmetric_key_t aeskey; psync_encrypted_symmetric_key_t encaeskey; psync_crypto_aes256_ctr_encoder_decoder_t encoder; char *token, *localpath; uint64_t off; size_t rd; psync_socket_t sock; psync_file_t fd; uint32_t keylen, enctype; unsigned char hashhex[PSYNC_HASH_DIGEST_HEXLEN], buff[4096]; sock=*((psync_socket_t *)ptr); psync_free(ptr); debug(D_NOTICE, "got tcp connection"); if (unlikely_log(socket_read_all(sock, &packet, sizeof(packet)))) goto err0; if (unlikely_log(packet.keylen>PSYNC_P2P_RSA_SIZE) || unlikely_log(packet.tokenlen>512)) /* lets allow 8 times larger keys than we use */ goto err0; localfileid=psync_p2p_has_file(packet.hashstart, packet.genhash, packet.rand, packet.filesize, hashhex); if (!localfileid){ debug(D_WARNING, "got request for file that we do not have"); goto err0; } binpubrsa=psync_ssl_alloc_binary_rsa(packet.keylen); if (unlikely_log(socket_read_all(sock, binpubrsa->data, binpubrsa->datalen))){ psync_free(binpubrsa); goto err0; } token=psync_new_cnt(char, packet.tokenlen); if (unlikely_log(socket_read_all(sock, token, packet.tokenlen)) || unlikely_log(!check_token(token, packet.tokenlen, binpubrsa->data, packet.keylen, hashhex))){ psync_free(binpubrsa); psync_free(token); goto err0; } psync_free(token); pubrsa=psync_ssl_rsa_binary_to_public(binpubrsa); psync_free(binpubrsa); if (unlikely_log(pubrsa==PSYNC_INVALID_RSA)) goto err0; localpath=psync_local_path_for_local_file(localfileid, NULL); if (unlikely_log(!localpath)) goto err0; fd=psync_file_open(localpath, P_O_RDONLY, 0); debug(D_NOTICE, "sending file %s to peer", localpath); psync_free(localpath); if (fd==INVALID_HANDLE_VALUE){ debug(D_WARNING, "could not open local file %lu", (unsigned long)localfileid); goto err0; } aeskey=psync_crypto_aes256_ctr_gen_key(); encaeskey=psync_ssl_rsa_encrypt_symmetric_key(pubrsa, aeskey); encoder=psync_crypto_aes256_ctr_encoder_decoder_create(aeskey); psync_ssl_free_symmetric_key(aeskey); keylen=encaeskey->datalen; enctype=P2P_ENCTYPE_RSA_AES; if (unlikely_log(encaeskey==PSYNC_INVALID_ENC_SYM_KEY) || unlikely_log(encoder==PSYNC_CRYPTO_INVALID_ENCODER) || unlikely_log(socket_write_all(sock, &keylen, sizeof(keylen)) || socket_write_all(sock, &enctype, sizeof(enctype)) || socket_write_all(sock, encaeskey->data, encaeskey->datalen))){ if (encaeskey!=PSYNC_INVALID_ENC_SYM_KEY) psync_free(encaeskey); if (encoder!=PSYNC_CRYPTO_INVALID_ENCODER) psync_crypto_aes256_ctr_encoder_decoder_free(encoder); psync_file_close(fd); goto err0; } psync_free(encaeskey); off=0; while (off<packet.filesize){ if (packet.filesize-off<sizeof(buff)) rd=packet.filesize-off; else rd=sizeof(buff); if (unlikely_log(psync_file_read(fd, buff, rd)!=rd)) break; psync_crypto_aes256_ctr_encode_decode_inplace(encoder, buff, rd, off); if (unlikely_log(socket_write_all(sock, buff, rd))) break; off+=rd; } psync_crypto_aes256_ctr_encoder_decoder_free(encoder); psync_file_close(fd); debug(D_NOTICE, "file sent successfuly"); err0: psync_close_socket(sock); }