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; }