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);
}
Beispiel #2
0
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;
}
Beispiel #3
0
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);
}