Ticket #1617: 0002-Use-a-chained-BIO-to-return-data-from-c-buffer.patch

File 0002-Use-a-chained-BIO-to-return-data-from-c-buffer.patch, 4.6 KB (added by James Callahan, 8 years ago)
  • src/event/ngx_event_openssl.c

    From a2c745a2c3b133b6c6c3b3a759f624a70af834ab Mon Sep 17 00:00:00 2001
    From: James Callahan <james@konghq.com>
    Date: Thu, 23 Aug 2018 12:57:07 +1000
    Subject: [PATCH 2/2] Use a chained BIO to return data from c->buffer
    
    ---
     src/event/ngx_event_openssl.c | 117 +++++++++++++++++++++++++++++++++-
     src/event/ngx_event_openssl.h |   3 +
     2 files changed, 119 insertions(+), 1 deletion(-)
    
    diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
    index e90690d3..22d74dce 100644
    a b ngx_ssl_init(ngx_log_t *log)  
    229229}
    230230
    231231
     232static int bio_read(BIO *bio, char *dst, int lim) {
     233    ngx_buf_t  *buf;
     234    BIO        *next_bio;
     235    int         count;
     236
     237    if (dst == NULL)
     238        return 0;
     239
     240    buf = BIO_get_data(bio);
     241    count = ngx_buf_size(buf);
     242
     243    if (count > 0) {
     244        BIO_clear_retry_flags(bio);
     245
     246        if (lim < count) {
     247            count = lim;
     248        }
     249
     250        memcpy(dst, buf->pos, count);
     251        buf->pos += count;
     252
     253        return count;
     254    }
     255
     256    next_bio = BIO_next(bio);
     257    if (next_bio == NULL)
     258        return 0;
     259
     260    count = BIO_read(next_bio, dst, lim);
     261    BIO_clear_retry_flags(bio);
     262    BIO_copy_next_retry(bio);
     263
     264    return count;
     265}
     266
     267
     268#if ((OPENSSL_VERSION_NUMBER < 0x10100001L && !defined LIBRESSL_VERSION_NUMBER))
     269static BIO_METHOD bio_methods = {
     270    BIO_TYPE_FILTER,
     271    "ngx_buf",
     272    nullf_write,
     273    bio_read,
     274    nullf_puts,
     275    nullf_gets,
     276    nullf_ctrl,
     277    nullf_new,
     278    nullf_free,
     279    nullf_callback_ctrl,
     280};
     281
     282BIO_METHOD *ngx_buf_bio_methods() {
     283    return &bio_methods;
     284} /* ngx_buf_bio_methods() */
     285#else
     286static BIO_METHOD *bio_methods = NULL;
     287
     288static CRYPTO_ONCE bio_methods_init_once = CRYPTO_ONCE_STATIC_INIT;
     289
     290static void bio_methods_init(void) {
     291    BIO_METHOD  *null_methods;
     292    int          type;
     293
     294    type = BIO_get_new_index();
     295    if (type == -1)
     296        return;
     297
     298    bio_methods = BIO_meth_new(type|BIO_TYPE_FILTER, "ngx_buf");
     299    if (bio_methods == NULL)
     300        return;
     301
     302    /* Same as null method but prepends when reading */
     303    null_methods = BIO_s_null();
     304    BIO_meth_set_write(bio_methods, BIO_meth_get_write(null_methods));
     305    BIO_meth_set_read(bio_methods, bio_read);
     306    BIO_meth_set_puts(bio_methods, BIO_meth_get_puts(null_methods));
     307    BIO_meth_set_ctrl(bio_methods, BIO_meth_get_ctrl(null_methods));
     308    BIO_meth_set_create(bio_methods, BIO_meth_get_create(null_methods));
     309    BIO_meth_set_destroy(bio_methods, BIO_meth_get_destroy(null_methods));
     310    BIO_meth_set_callback_ctrl(bio_methods, BIO_meth_get_callback_ctrl(null_methods));
     311} /* bio_methods_init() */
     312
     313BIO_METHOD *ngx_buf_bio_methods() {
     314    if (bio_methods == NULL) {
     315        CRYPTO_THREAD_run_once(&bio_methods_init_once, bio_methods_init);
     316    }
     317    return bio_methods;
     318} /* ngx_buf_bio_methods() */
     319#endif
     320
     321
    232322ngx_int_t
    233323ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data)
    234324{
    ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c, ngx_uint_t flags)  
    11901280    }
    11911281
    11921282    if (c->buffer && ngx_buf_size(c->buffer) != 0) {
    1193         ngx_ssl_error(NGX_LOG_WARN, c->log, 0, "Ignoring %d bytes of buffered data", ngx_buf_size(c->buffer));
     1283        if (ngx_buf_in_memory_only(c->buffer)) {
     1284            BIO_METHOD  *bio_methods;
     1285            BIO         *bio, *oldbio;
     1286
     1287            bio_methods = ngx_buf_bio_methods();
     1288            if (bio_methods == NULL) {
     1289                ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "ngx_buf_bio_methods() failed");
     1290                return NGX_ERROR;
     1291            }
     1292
     1293            bio = BIO_new(bio_methods);
     1294            if (bio == NULL) {
     1295                ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "BIO_new() failed");
     1296                return NGX_ERROR;
     1297            }
     1298
     1299            BIO_set_data(bio, c->buffer);
     1300
     1301            /* need to increment as SSL_set0_rbio decrements */
     1302            oldbio = SSL_get_rbio(sc->connection);
     1303            BIO_up_ref(oldbio);
     1304            SSL_set0_rbio(sc->connection, BIO_push(bio, oldbio));
     1305
     1306        } else {
     1307            ngx_ssl_error(NGX_LOG_WARN, c->log, 0, "Ignoring %d bytes of buffered data", ngx_buf_size(c->buffer));
     1308        }
    11941309    }
    11951310
    11961311    if (flags & NGX_SSL_CLIENT) {
  • src/event/ngx_event_openssl.h

    diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h
    index b9a3a965..4f858048 100644
    a b  
    5959#endif
    6060
    6161
     62BIO_METHOD *ngx_buf_bio_methods();
     63
     64
    6265struct ngx_ssl_s {
    6366    SSL_CTX                    *ctx;
    6467    ngx_log_t                  *log;