コード例 #1
0
/* Returns the amount written. */
static int bio_bucket_write(BIO *bio, const char *in, int inl)
{
    serf_ssl_context_t *ctx = bio->ptr;
    serf_bucket_t *tmp;

#ifdef SSL_VERBOSE
    printf("bio_bucket_write called for %d bytes\n", inl);
#endif
    if (ctx->encrypt.status == SERF_ERROR_WAIT_CONN
        && !BIO_should_read(ctx->bio)) {
#ifdef SSL_VERBOSE
        printf("bio_bucket_write waiting: (%d %d %d)\n",
           BIO_should_retry(ctx->bio), BIO_should_read(ctx->bio),
           BIO_get_retry_flags(ctx->bio));
#endif
        /* Falling back... */
        ctx->encrypt.exhausted_reset = 1;
        BIO_clear_retry_flags(bio);
    }

    tmp = serf_bucket_simple_copy_create(in, inl,
                                         ctx->encrypt.pending->allocator);

    serf_bucket_aggregate_append(ctx->encrypt.pending, tmp);

    return inl;
}
コード例 #2
0
ファイル: pair.c プロジェクト: 360ground/Meda.et
int BIO_zero_copy_get_read_buf_done(BIO* bio, size_t bytes_read) {
  struct bio_bio_st* b;
  struct bio_bio_st* peer_b;
  size_t max_available;
  size_t dummy_read_offset;
  uint8_t* dummy_read_buf;

  assert(BIO_get_retry_flags(bio) == 0);

  if (!bio->init) {
    OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
    return 0;
  }

  b = bio->ptr;

  if (!b || !b->peer) {
    OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
    return 0;
  }

  peer_b = b->peer->ptr;
  if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
    OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
    return 0;
  }

  if (!peer_b->zero_copy_read_lock) {
    OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
    return 0;
  }

  max_available =
      bio_zero_copy_get_read_buf(peer_b, &dummy_read_buf, &dummy_read_offset);
  if (bytes_read > max_available) {
    OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
    return 0;
  }

  peer_b->len -= bytes_read;
  assert(peer_b->len >= 0);
  assert(peer_b->offset + bytes_read <= peer_b->size);

  /* Move read offset. If zero_copy_write_lock == 1 we must advance the
   * offset even if buffer becomes empty, to make sure
   * write_offset = (offset + len) mod size does not change. */
  if (peer_b->offset + bytes_read == peer_b->size ||
      (!peer_b->zero_copy_write_lock && peer_b->len == 0)) {
    peer_b->offset = 0;
  } else {
    peer_b->offset += bytes_read;
  }

  bio->num_read += bytes_read;
  peer_b->zero_copy_read_lock = 0;
  return 1;
}
コード例 #3
0
/* Returns the amount read. */
static int bio_bucket_read(BIO *bio, char *in, int inlen)
{
    serf_ssl_context_t *ctx = bio->ptr;
    const char *data;
    apr_status_t status;
    apr_size_t len;

#ifdef SSL_VERBOSE
    printf("bio_bucket_read called for %d bytes\n", inlen);
#endif

    if (ctx->encrypt.status == SERF_ERROR_WAIT_CONN
        && BIO_should_read(ctx->bio)) {
#ifdef SSL_VERBOSE
        printf("bio_bucket_read waiting: (%d %d %d)\n",
           BIO_should_retry(ctx->bio), BIO_should_read(ctx->bio),
           BIO_get_retry_flags(ctx->bio));
#endif
        /* Falling back... */
        ctx->encrypt.exhausted_reset = 1;
        BIO_clear_retry_flags(bio);
    }

    status = serf_bucket_read(ctx->decrypt.pending, inlen, &data, &len);

    ctx->decrypt.status = status;
#ifdef SSL_VERBOSE
    printf("bio_bucket_read received %d bytes (%d)\n", len, status);
#endif

    if (!SERF_BUCKET_READ_ERROR(status)) {
        /* Oh suck. */
        if (len) {
            memcpy(in, data, len);
            return len;
        }
        if (APR_STATUS_IS_EOF(status)) {
            BIO_set_retry_read(bio);
            return -1;
        }
    }

    return -1;
}
コード例 #4
0
ファイル: bio.c プロジェクト: RobinWuDev/Qt
void BIO_copy_next_retry(BIO *bio) {
  BIO_clear_retry_flags(bio);
  BIO_set_flags(bio, BIO_get_retry_flags(bio->next_bio));
  bio->retry_reason = bio->next_bio->retry_reason;
}
コード例 #5
0
ファイル: bio_lib.c プロジェクト: 002301/node
void BIO_copy_next_retry(BIO *b)
	{
	BIO_set_flags(b,BIO_get_retry_flags(b->next_bio));
	b->retry_reason=b->next_bio->retry_reason;
	}
コード例 #6
0
/* This function reads a decrypted stream and returns an encrypted stream. */
static apr_status_t ssl_encrypt(void *baton, apr_size_t bufsize,
                                char *buf, apr_size_t *len)
{
    const char *data;
    apr_size_t interim_bufsize;
    serf_ssl_context_t *ctx = baton;
    apr_status_t status;

#ifdef SSL_VERBOSE
    printf("ssl_encrypt: begin %d\n", bufsize);
#endif

    /* Try to read already encrypted but unread data first. */
    status = serf_bucket_read(ctx->encrypt.pending, bufsize, &data, len);
    if (SERF_BUCKET_READ_ERROR(status)) {
        return status;
    }

    /* Aha, we read something.  Return that now. */
    if (*len) {
        memcpy(buf, data, *len);
        if (APR_STATUS_IS_EOF(status)) {
            status = APR_SUCCESS;
        }
#ifdef SSL_VERBOSE
        printf("ssl_encrypt: %d %d %d (quick read)\n", status, *len,
               BIO_get_retry_flags(ctx->bio));
#endif
        return status;
    }

    if (BIO_should_retry(ctx->bio) && BIO_should_write(ctx->bio)) {
#ifdef SSL_VERBOSE
        printf("ssl_encrypt: %d %d %d (should write exit)\n", status, *len,
               BIO_get_retry_flags(ctx->bio));
#endif
        return APR_EAGAIN;
    }

    /* If we were previously blocked, unblock ourselves now. */
    if (BIO_should_read(ctx->bio)) {
#ifdef SSL_VERBOSE
        printf("ssl_encrypt: reset %d %d (%d %d %d)\n", status,
               ctx->encrypt.status,
           BIO_should_retry(ctx->bio), BIO_should_read(ctx->bio),
           BIO_get_retry_flags(ctx->bio));
#endif
        ctx->encrypt.status = APR_SUCCESS;
        ctx->encrypt.exhausted_reset = 0;
    }

    /* Oh well, read from our stream now. */
    interim_bufsize = bufsize;
    do {
        apr_size_t interim_len;

        if (!ctx->encrypt.status) {
            struct iovec vecs[64];
            int vecs_read;

            status = serf_bucket_read_iovec(ctx->encrypt.stream,
                                            interim_bufsize, 64, vecs,
                                            &vecs_read);

            if (!SERF_BUCKET_READ_ERROR(status) && vecs_read) {
                char *vecs_data;
                int i, cur, vecs_data_len;
                int ssl_len;

                /* Combine the buffers of the iovec into one buffer, as
                   that is with SSL_write requires. */
                vecs_data_len = 0;
                for (i = 0; i < vecs_read; i++) {
                    vecs_data_len += vecs[i].iov_len;
                }

                vecs_data = serf_bucket_mem_alloc(ctx->allocator,
                                                  vecs_data_len);

                cur = 0;
                for (i = 0; i < vecs_read; i++) {
                    memcpy(vecs_data + cur, vecs[i].iov_base, vecs[i].iov_len);
                    cur += vecs[i].iov_len;
                }

                interim_bufsize -= vecs_data_len;
                interim_len = vecs_data_len;

#ifdef SSL_VERBOSE
                printf("ssl_encrypt: bucket read %d bytes; status %d\n",
                       interim_len, status);
                printf("---\n%s\n-(%d)-\n", vecs_data, interim_len);
#endif
                /* Stash our status away. */
                ctx->encrypt.status = status;

                ssl_len = SSL_write(ctx->ssl, vecs_data, interim_len);
#ifdef SSL_VERBOSE
                printf("ssl_encrypt: SSL write: %d\n", ssl_len);
#endif
                /* We're done. */
                serf_bucket_mem_free(ctx->allocator, vecs_data);

                /* If we failed to write... */
                if (ssl_len < 0) {
                    int ssl_err;

                    /* Ah, bugger. We need to put that data back. */
                    serf_bucket_aggregate_prepend_iovec(ctx->encrypt.stream,
                                                        vecs, vecs_read);

                    ssl_err = SSL_get_error(ctx->ssl, ssl_len);
#ifdef SSL_VERBOSE
                    printf("ssl_encrypt: SSL write error: %d\n", ssl_err);
#endif
                    if (ssl_err == SSL_ERROR_SYSCALL) {
                        status = ctx->encrypt.status;
                        if (SERF_BUCKET_READ_ERROR(status)) {
                            return status;
                        }
                    }
                    else {
                        /* Oh, no. */
                        if (ssl_err == SSL_ERROR_WANT_READ) {
                            status = SERF_ERROR_WAIT_CONN;
                        }
                        else {
                            status = APR_EGENERAL;
                        }
                    }
#ifdef SSL_VERBOSE
                    printf("ssl_encrypt: SSL write error: %d %d\n", status, *len);
#endif
                }
            }
        }
        else {
            interim_len = 0;
            *len = 0;
            status = ctx->encrypt.status;
        }

    } while (!status && interim_bufsize);

    /* Okay, we exhausted our underlying stream. */
    if (!SERF_BUCKET_READ_ERROR(status)) {
        apr_status_t agg_status;
        struct iovec vecs[64];
        int vecs_read, i;

        /* We read something! */
        agg_status = serf_bucket_read_iovec(ctx->encrypt.pending, bufsize,
                                            64, vecs, &vecs_read);
        *len = 0;
        for (i = 0; i < vecs_read; i++) {
            memcpy(buf + *len, vecs[i].iov_base, vecs[i].iov_len);
            *len += vecs[i].iov_len;
        }

#ifdef SSL_VERBOSE
        printf("ssl_encrypt read agg: %d %d %d %d\n", status, agg_status,
               ctx->encrypt.status, *len);
#endif

        if (!agg_status) {
            status = agg_status;
        }
    }

    if (status == SERF_ERROR_WAIT_CONN
        && BIO_should_retry(ctx->bio) && BIO_should_read(ctx->bio)) {
        ctx->encrypt.exhausted = ctx->encrypt.status;
        ctx->encrypt.status = SERF_ERROR_WAIT_CONN;
    }

#ifdef SSL_VERBOSE
    printf("ssl_encrypt finished: %d %d (%d %d %d)\n", status, *len,
           BIO_should_retry(ctx->bio), BIO_should_read(ctx->bio),
           BIO_get_retry_flags(ctx->bio));
#endif
    return status;
}
コード例 #7
0
/* This function reads an encrypted stream and returns the decrypted stream. */
static apr_status_t ssl_decrypt(void *baton, apr_size_t bufsize,
                                char *buf, apr_size_t *len)
{
    serf_ssl_context_t *ctx = baton;
    apr_size_t priv_len;
    apr_status_t status;
    const char *data;
    int ssl_len;

#ifdef SSL_VERBOSE
    printf("ssl_decrypt: begin %d\n", bufsize);
#endif

    /* Is there some data waiting to be read? */
    ssl_len = SSL_read(ctx->ssl, buf, bufsize);
    if (ssl_len > 0) {
#ifdef SSL_VERBOSE
        printf("ssl_decrypt: %d bytes (%d); status: %d; flags: %d\n",
               ssl_len, bufsize, ctx->decrypt.status,
               BIO_get_retry_flags(ctx->bio));
#endif
        *len = ssl_len;
        return APR_SUCCESS;
    }

    status = serf_bucket_read(ctx->decrypt.stream, bufsize, &data, &priv_len);

    if (!SERF_BUCKET_READ_ERROR(status) && priv_len) {
        serf_bucket_t *tmp;

#ifdef SSL_VERBOSE
        printf("ssl_decrypt: read %d bytes (%d); status: %d\n", priv_len,
               bufsize, status);
#endif

        tmp = serf_bucket_simple_copy_create(data, priv_len,
                                             ctx->decrypt.pending->allocator);

        serf_bucket_aggregate_append(ctx->decrypt.pending, tmp);

        ssl_len = SSL_read(ctx->ssl, buf, bufsize);
        if (ssl_len < 0) {
            int ssl_err;

            ssl_err = SSL_get_error(ctx->ssl, ssl_len);
            switch (ssl_err) {
            case SSL_ERROR_SYSCALL:
                *len = 0;
                status = ctx->decrypt.status;
                break;
            case SSL_ERROR_WANT_READ:
                *len = 0;
                status = APR_EAGAIN;
                break;
            case SSL_ERROR_SSL:
                *len = 0;
                status = ctx->pending_err ? ctx->pending_err : APR_EGENERAL;
                ctx->pending_err = 0;
                break;
            default:
                *len = 0;
                status = APR_EGENERAL;
                break;
            }
        }
        else {
            *len = ssl_len;
#ifdef SSL_VERBOSE
            printf("---\n%s\n-(%d)-\n", buf, *len);
#endif
        }
    }
    else {
        *len = 0;
    }
#ifdef SSL_VERBOSE
    printf("ssl_decrypt: %d %d %d\n", status, *len,
           BIO_get_retry_flags(ctx->bio));
#endif
    return status;
}