Ejemplo n.º 1
0
static int
send_encrypted_block (BlockTxServer *server,
                      BlockHandle *handle,
                      const char *block_id,
                      int size)
{
    int n, remain;
    int ret = 0;
    EVP_CIPHER_CTX ctx;
    char send_buf[SEND_BUFFER_SIZE];

    if (server->version == 1)
        blocktx_encrypt_init (&ctx, server->key, server->iv);
    else if (server->version == 2)
        blocktx_encrypt_init (&ctx, server->key_v2, server->iv_v2);

    if (send_encrypted_data_frame_begin (server->data_fd, size) < 0) {
        seaf_warning ("Send block %s: failed to begin.\n", block_id);
        ret = -1;
        goto out;
    }

    remain = size;
    while (remain > 0) {
        n = seaf_block_manager_read_block (seaf->block_mgr,
                                           handle,
                                           send_buf, SEND_BUFFER_SIZE);
        if (n < 0) {
            seaf_warning ("Failed to read block %s.\n", block_id);
            ret = -1;
            goto out;
        }

        if (send_encrypted_data (&ctx, server->data_fd, send_buf, n) < 0) {
            seaf_warning ("Send block %s: failed to send data.\n", block_id);
            ret = -1;
            goto out;
        }

        remain -= n;
    }

    if (send_encrypted_data_frame_end (&ctx, server->data_fd) < 0) {
        seaf_warning ("Send block %s: failed to end.\n", block_id);
        ret = -1;
        goto out;
    }

    seaf_debug ("Send block %s done.\n", server->curr_block_id);

out:
    EVP_CIPHER_CTX_cleanup (&ctx);
    return ret;
}
Ejemplo n.º 2
0
static int
send_authentication (BlockTxClient *client)
{
    TransferTask *task = client->info->task;
    EVP_CIPHER_CTX ctx;
    int ret = 0;

    if (client->version == 1)
        blocktx_encrypt_init (&ctx, client->key, client->iv);
    else if (client->version == 2)
        blocktx_encrypt_init (&ctx, client->key_v2, client->iv_v2);

    seaf_debug ("session token length is %d.\n", strlen(task->session_token));

    if (send_encrypted_data_frame_begin (client->data_fd,
                                         strlen(task->session_token) + 1) < 0) {
        seaf_warning ("Send auth request: failed to begin.\n");
        client->info->result = BLOCK_CLIENT_NET_ERROR;
        ret = -1;
        goto out;
    }

    if (send_encrypted_data (&ctx, client->data_fd,
                             task->session_token,
                             strlen(task->session_token) + 1) < 0)
    {
        seaf_warning ("Send auth request: failed to send data.\n");
        client->info->result = BLOCK_CLIENT_NET_ERROR;
        ret = -1;
        goto out;
    }

    if (send_encrypted_data_frame_end (&ctx, client->data_fd) < 0) {
        seaf_warning ("Send auth request: failed to end.\n");
        client->info->result = BLOCK_CLIENT_NET_ERROR;
        ret = -1;
        goto out;
    }

    seaf_debug ("recv_state set to AUTH.\n");

    client->parser.content_cb = handle_auth_rsp_content_cb;
    client->recv_state = RECV_STATE_AUTH;

out:
    EVP_CIPHER_CTX_cleanup (&ctx);
    return ret;
}
Ejemplo n.º 3
0
static int
send_block_header (BlockTxClient *client, int command)
{
    RequestHeader header;
    EVP_CIPHER_CTX ctx;
    int ret = 0;

    header.command = htonl (command);
    memcpy (header.block_id, client->curr_block_id, 40);

    if (client->version == 1)
        blocktx_encrypt_init (&ctx, client->key, client->iv);
    else if (client->version == 2)
        blocktx_encrypt_init (&ctx, client->key_v2, client->iv_v2);

    if (send_encrypted_data_frame_begin (client->data_fd, sizeof(header)) < 0) {
        seaf_warning ("Send block header %s: failed to begin.\n",
                      client->curr_block_id);
        client->info->result = BLOCK_CLIENT_NET_ERROR;
        ret = -1;
        goto out;
    }

    if (send_encrypted_data (&ctx, client->data_fd,
                             &header, sizeof(header)) < 0)
    {
        seaf_warning ("Send block header %s: failed to send data.\n",
                      client->curr_block_id);
        client->info->result = BLOCK_CLIENT_NET_ERROR;
        ret = -1;
        goto out;
    }

    if (send_encrypted_data_frame_end (&ctx, client->data_fd) < 0) {
        seaf_warning ("Send block header %s: failed to end.\n",
                      client->curr_block_id);
        client->info->result = BLOCK_CLIENT_NET_ERROR;
        ret = -1;
        goto out;
    }

out:
    EVP_CIPHER_CTX_cleanup (&ctx);
    return ret;
}
Ejemplo n.º 4
0
static int
send_block_response_header (BlockTxServer *server, int status)
{
    ResponseHeader header;
    EVP_CIPHER_CTX ctx;
    int ret = 0;

    header.status = htonl (status);

    if (server->version == 1)
        blocktx_encrypt_init (&ctx, server->key, server->iv);
    else if (server->version == 2)
        blocktx_encrypt_init (&ctx, server->key_v2, server->iv_v2);

    if (send_encrypted_data_frame_begin (server->data_fd, sizeof(header)) < 0) {
        seaf_warning ("Send block response header %s: failed to begin.\n",
                      server->curr_block_id);
        ret = -1;
        goto out;
    }

    if (send_encrypted_data (&ctx, server->data_fd,
                             &header, sizeof(header)) < 0)
    {
        seaf_warning ("Send block response header %s: failed to send data.\n",
                      server->curr_block_id);
        ret = -1;
        goto out;
    }

    if (send_encrypted_data_frame_end (&ctx, server->data_fd) < 0) {
        seaf_warning ("Send block response header %s: failed to end.\n",
                      server->curr_block_id);
        ret = -1;
        goto out;
    }

out:
    EVP_CIPHER_CTX_cleanup (&ctx);
    return ret;
}
Ejemplo n.º 5
0
static int
send_auth_response (BlockTxServer *server, int status)
{
    AuthResponse rsp;
    EVP_CIPHER_CTX ctx;
    int ret = 0;

    rsp.status = htonl (status);

    if (server->version == 1)
        blocktx_encrypt_init (&ctx, server->key, server->iv);
    else if (server->version == 2)
        blocktx_encrypt_init (&ctx, server->key_v2, server->iv_v2);

    if (send_encrypted_data_frame_begin (server->data_fd, sizeof(rsp)) < 0) {
        seaf_warning ("Send auth response: failed to begin.\n");
        ret = -1;
        goto out;
    }

    if (send_encrypted_data (&ctx, server->data_fd, &rsp, sizeof(rsp)) < 0)
    {
        seaf_warning ("Send auth response: failed to send data.\n");
        ret = -1;
        goto out;
    }

    if (send_encrypted_data_frame_end (&ctx, server->data_fd) < 0) {
        seaf_warning ("Send auth response: failed to end.\n");
        ret = -1;
        goto out;
    }

out:
    EVP_CIPHER_CTX_cleanup (&ctx);
    return ret;
}
Ejemplo n.º 6
0
/**
 * Send data read from an already open file descriptor.
 *
 * We return 1 on sucess and 0 on errors.
 *
 * ***FIXME***
 * We use ff_pkt->statp.st_size when FO_SPARSE to know when to stop reading.
 * Currently this is not a problem as the only other stream, resource forks,
 * are not handled as sparse files.
 */
static int send_data(JCR *jcr, int stream, FF_PKT *ff_pkt,
                     DIGEST *digest, DIGEST *signing_digest)
{
   b_ctx bctx;
   BSOCK *sd = jcr->store_bsock;
#ifdef FD_NO_SEND_TEST
   return 1;
#endif

   /*
    * Setup backup context.
    */
   memset(&bctx, 0, sizeof(b_ctx));
   bctx.jcr = jcr;
   bctx.ff_pkt = ff_pkt;
   bctx.msgsave = sd->msg; /* save the original sd buffer */
   bctx.rbuf = sd->msg; /* read buffer */
   bctx.wbuf = sd->msg; /* write buffer */
   bctx.rsize = jcr->buf_size; /* read buffer size */
   bctx.cipher_input = (uint8_t *)bctx.rbuf; /* encrypt uncompressed data */
   bctx.digest = digest; /* encryption digest */
   bctx.signing_digest = signing_digest; /* signing digest */

   Dmsg1(300, "Saving data, type=%d\n", ff_pkt->type);

   if (!setup_compression_context(bctx)) {
      goto bail_out;
   }

   if (!setup_encryption_context(bctx)) {
      goto bail_out;
   }

   /*
    * Send Data header to Storage daemon
    *    <file-index> <stream> <info>
    */
   if (!sd->fsend("%ld %d 0", jcr->JobFiles, stream)) {
      if (!jcr->is_job_canceled()) {
         Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"), sd->bstrerror());
      }
      goto bail_out;
   }
   Dmsg1(300, ">stored: datahdr %s", sd->msg);

   /*
    * Make space at beginning of buffer for fileAddr because this
    *   same buffer will be used for writing if compression is off.
    */
   if (bit_is_set(FO_SPARSE, ff_pkt->flags) || bit_is_set(FO_OFFSETS, ff_pkt->flags)) {
      bctx.rbuf += OFFSET_FADDR_SIZE;
      bctx.rsize -= OFFSET_FADDR_SIZE;
#ifdef HAVE_FREEBSD_OS
      /*
       * To read FreeBSD partitions, the read size must be a multiple of 512.
       */
      bctx.rsize = (bctx.rsize / 512) * 512;
#endif
   }

   /*
    * A RAW device read on win32 only works if the buffer is a multiple of 512
    */
#ifdef HAVE_WIN32
   if (S_ISBLK(ff_pkt->statp.st_mode)) {
      bctx.rsize = (bctx.rsize / 512) * 512;
   }

   if (ff_pkt->statp.st_rdev & FILE_ATTRIBUTE_ENCRYPTED) {
      if (!send_encrypted_data(bctx)) {
         goto bail_out;
      }
   } else {
      if (!send_plain_data(bctx)) {
         goto bail_out;
      }
   }
#else
   if (!send_plain_data(bctx)) {
      goto bail_out;
   }
#endif

   if (sd->msglen < 0) { /* error */
      berrno be;
      Jmsg(jcr, M_ERROR, 0, _("Read error on file %s. ERR=%s\n"), ff_pkt->fname, be.bstrerror(ff_pkt->bfd.berrno));
      if (jcr->JobErrors++ > 1000) { /* insanity check */
         Jmsg(jcr, M_FATAL, 0, _("Too many errors. JobErrors=%d.\n"), jcr->JobErrors);
      }
   } else if (bit_is_set(FO_ENCRYPT, ff_pkt->flags)) {
      /*
       * For encryption, we must call finalize to push out any buffered data.
       */
      if (!crypto_cipher_finalize(bctx.cipher_ctx,
                                  (uint8_t *)jcr->crypto.crypto_buf,
                                  &bctx.encrypted_len)) {
         /*
          * Padding failed. Shouldn't happen.
          */
         Jmsg(jcr, M_FATAL, 0, _("Encryption padding error\n"));
         goto bail_out;
      }

      /*
       * Note, on SSL pre-0.9.7, there is always some output
       */
      if (bctx.encrypted_len > 0) {
         sd->msglen = bctx.encrypted_len; /* set encrypted length */
         sd->msg = jcr->crypto.crypto_buf; /* set correct write buffer */
         if (!sd->send()) {
            if (!jcr->is_job_canceled()) {
               Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"), sd->bstrerror());
            }
            goto bail_out;
         }
         Dmsg1(130, "Send data to SD len=%d\n", sd->msglen);
         jcr->JobBytes += sd->msglen; /* count bytes saved possibly compressed/encrypted */
         sd->msg = bctx.msgsave; /* restore bnet buffer */
      }
   }

   if (!sd->signal(BNET_EOD)) { /* indicate end of file data */
      if (!jcr->is_job_canceled()) {
         Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"), sd->bstrerror());
      }
      goto bail_out;
   }

   /*
    * Free the cipher context
    */
   if (bctx.cipher_ctx) {
      crypto_cipher_free(bctx.cipher_ctx);
   }

   return 1;

bail_out:
   /*
    * Free the cipher context
    */
   if (bctx.cipher_ctx) {
      crypto_cipher_free(bctx.cipher_ctx);
   }

   sd->msg = bctx.msgsave; /* restore bnet buffer */
   sd->msglen = 0;

   return 0;
}
Ejemplo n.º 7
0
static int
send_encrypted_block (BlockTxClient *client,
                      BlockHandle *handle,
                      const char *block_id)
{
    BlockTxInfo *info = client->info;
    BlockMetadata *md;
    int size, n, remain;
    int ret = 0;
    EVP_CIPHER_CTX ctx;
    char send_buf[SEND_BUFFER_SIZE];

    md = seaf_block_manager_stat_block_by_handle (seaf->block_mgr, handle);
    if (!md) {
        seaf_warning ("Failed to stat block %s.\n", block_id);
        client->info->result = BLOCK_CLIENT_FAILED;
        ret = -1;
        goto out;
    }
    size = md->size;
    g_free (md);

    if (client->version == 1)
        blocktx_encrypt_init (&ctx, client->key, client->iv);
    else if (client->version == 2)
        blocktx_encrypt_init (&ctx, client->key_v2, client->iv_v2);

    if (send_encrypted_data_frame_begin (client->data_fd, size) < 0) {
        seaf_warning ("Send block %s: failed to begin.\n", block_id);
        info->result = BLOCK_CLIENT_NET_ERROR;
        ret = -1;
        goto out;
    }

    remain = size;
    while (remain > 0) {
        if (info->task->state == TASK_STATE_CANCELED) {
            info->result = BLOCK_CLIENT_CANCELED;
            ret = -1;
            goto out;
        }

        n = seaf_block_manager_read_block (seaf->block_mgr,
                                           handle,
                                           send_buf, SEND_BUFFER_SIZE);
        if (n < 0) {
            seaf_warning ("Failed to read block %s.\n", block_id);
            info->result = BLOCK_CLIENT_FAILED;
            ret = -1;
            goto out;
        }

        if (send_encrypted_data (&ctx, client->data_fd, send_buf, n) < 0) {
            seaf_warning ("Send block %s: failed to send data.\n", block_id);
            info->result = BLOCK_CLIENT_NET_ERROR;
            ret = -1;
            goto out;
        }

        /* Update global transferred bytes. */
        g_atomic_int_add (&(info->task->tx_bytes), n);
        g_atomic_int_add (&(seaf->sync_mgr->sent_bytes), n);

        /* If uploaded bytes exceeds the limit, wait until the counter
         * is reset. We check the counter every 100 milliseconds, so we
         * can waste up to 100 milliseconds without sending data after
         * the counter is reset.
         */
        while (1) {
            gint sent = g_atomic_int_get(&(seaf->sync_mgr->sent_bytes));
            if (seaf->sync_mgr->upload_limit > 0 &&
                sent > seaf->sync_mgr->upload_limit)
                /* 100 milliseconds */
                G_USLEEP (100000);
            else
                break;
        }

        remain -= n;
    }

    if (send_encrypted_data_frame_end (&ctx, client->data_fd) < 0) {
        seaf_warning ("Send block %s: failed to end.\n", block_id);
        info->result = BLOCK_CLIENT_NET_ERROR;
        ret = -1;
        goto out;
    }

out:
    EVP_CIPHER_CTX_cleanup (&ctx);
    return ret;
}