static jint socket_read (JNIEnv *env, jobject object, jobject fileDescriptor)
{
    int fd;
    int err;

    if (fileDescriptor == NULL) {
        jniThrowNullPointerException(env, NULL);
        return (jint)-1;
    }

    fd = jniGetFDFromFileDescriptor(env, fileDescriptor);

    if (env->ExceptionCheck()) {
        return (jint)0;
    }

    unsigned char buf;

    err = socket_read_all(env, object, fd, &buf, 1);

    if (err < 0) {
        jniThrowIOException(env, errno);
        return (jint)0;
    }

    if (err == 0) {
        // end of file
        return (jint)-1;
    }

    return (jint)buf;
}
static jint socket_readba (JNIEnv *env, jobject object,
        jbyteArray buffer, jint off, jint len, jobject fileDescriptor)
{
    int fd;
    jbyte* byteBuffer;
    int ret;

    if (fileDescriptor == NULL || buffer == NULL) {
        jniThrowNullPointerException(env, NULL);
        return (jint)-1;
    }

    if (off < 0 || len < 0 || (off + len) > env->GetArrayLength(buffer)) {
        jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL);
        return (jint)-1;
    }

    if (len == 0) {
        // because socket_read_all returns 0 on EOF
        return 0;
    }

    fd = jniGetFDFromFileDescriptor(env, fileDescriptor);

    if (env->ExceptionCheck()) {
        return (jint)-1;
    }

    byteBuffer = env->GetByteArrayElements(buffer, NULL);

    if (NULL == byteBuffer) {
        // an exception will have been thrown
        return (jint)-1;
    }

    ret = socket_read_all(env, object,
            fd, byteBuffer + off, len);

    // A return of -1 above means an exception is pending

    env->ReleaseByteArrayElements(buffer, byteBuffer, 0);

    return (jint) ((ret == 0) ? -1 : ret);
}
Exemple #3
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;
}
Exemple #4
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);
}