diff options
Diffstat (limited to 'tls_bio_cb.c')
-rw-r--r-- | tls_bio_cb.c | 65 |
1 files changed, 46 insertions, 19 deletions
diff --git a/tls_bio_cb.c b/tls_bio_cb.c index 0091808..dad9d23 100644 --- a/tls_bio_cb.c +++ b/tls_bio_cb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_bio_cb.c,v 1.19 2017/01/12 16:18:39 jsing Exp $ */ +/* $OpenBSD: tls_bio_cb.c,v 1.20 2022/01/10 23:39:48 tb Exp $ */ /* * Copyright (c) 2016 Tobias Pape <tobias@netshed.de> * @@ -29,19 +29,41 @@ static int bio_cb_read(BIO *bio, char *buf, int size); static int bio_cb_puts(BIO *bio, const char *str); static long bio_cb_ctrl(BIO *bio, int cmd, long num, void *ptr); -static BIO_METHOD bio_cb_method = { - .type = BIO_TYPE_MEM, - .name = "libtls_callbacks", - .bwrite = bio_cb_write, - .bread = bio_cb_read, - .bputs = bio_cb_puts, - .ctrl = bio_cb_ctrl, -}; +static BIO_METHOD *bio_cb_method; + +static pthread_mutex_t bio_cb_method_lock = PTHREAD_MUTEX_INITIALIZER; + +static void +bio_cb_method_init(void) +{ + BIO_METHOD *bio_method; + + if (bio_cb_method != NULL) + return; + + bio_method = BIO_meth_new(BIO_TYPE_MEM, "libtls_callbacks"); + if (bio_method == NULL) + return; + + BIO_meth_set_write(bio_method, bio_cb_write); + BIO_meth_set_read(bio_method, bio_cb_read); + BIO_meth_set_puts(bio_method, bio_cb_puts); + BIO_meth_set_ctrl(bio_method, bio_cb_ctrl); + + bio_cb_method = bio_method; +} static BIO_METHOD * bio_s_cb(void) { - return (&bio_cb_method); + if (bio_cb_method != NULL) + return (bio_cb_method); + + pthread_mutex_lock(&bio_cb_method_lock); + bio_cb_method_init(); + pthread_mutex_unlock(&bio_cb_method_lock); + + return (bio_cb_method); } static int @@ -57,10 +79,10 @@ bio_cb_ctrl(BIO *bio, int cmd, long num, void *ptr) switch (cmd) { case BIO_CTRL_GET_CLOSE: - ret = (long)bio->shutdown; + ret = (long)BIO_get_shutdown(bio); break; case BIO_CTRL_SET_CLOSE: - bio->shutdown = (int)num; + BIO_set_shutdown(bio, (int)num); break; case BIO_CTRL_DUP: case BIO_CTRL_FLUSH: @@ -69,7 +91,7 @@ bio_cb_ctrl(BIO *bio, int cmd, long num, void *ptr) case BIO_CTRL_GET: case BIO_CTRL_SET: default: - ret = BIO_ctrl(bio->next_bio, cmd, num, ptr); + ret = BIO_ctrl(BIO_next(bio), cmd, num, ptr); } return (ret); @@ -78,7 +100,7 @@ bio_cb_ctrl(BIO *bio, int cmd, long num, void *ptr) static int bio_cb_write(BIO *bio, const char *buf, int num) { - struct tls *ctx = bio->ptr; + struct tls *ctx = BIO_get_data(bio); int rv; BIO_clear_retry_flags(bio); @@ -96,7 +118,7 @@ bio_cb_write(BIO *bio, const char *buf, int num) static int bio_cb_read(BIO *bio, char *buf, int size) { - struct tls *ctx = bio->ptr; + struct tls *ctx = BIO_get_data(bio); int rv; BIO_clear_retry_flags(bio); @@ -115,8 +137,9 @@ int tls_set_cbs(struct tls *ctx, tls_read_cb read_cb, tls_write_cb write_cb, void *cb_arg) { - int rv = -1; + const BIO_METHOD *bio_cb; BIO *bio; + int rv = -1; if (read_cb == NULL || write_cb == NULL) { tls_set_errorx(ctx, "no callbacks provided"); @@ -127,12 +150,16 @@ tls_set_cbs(struct tls *ctx, tls_read_cb read_cb, tls_write_cb write_cb, ctx->write_cb = write_cb; ctx->cb_arg = cb_arg; - if ((bio = BIO_new(bio_s_cb())) == NULL) { + if ((bio_cb = bio_s_cb()) == NULL) { + tls_set_errorx(ctx, "failed to create callback method"); + goto err; + } + if ((bio = BIO_new(bio_cb)) == NULL) { tls_set_errorx(ctx, "failed to create callback i/o"); goto err; } - bio->ptr = ctx; - bio->init = 1; + BIO_set_data(bio, ctx); + BIO_set_init(bio, 1); SSL_set_bio(ctx->ssl_conn, bio, bio); |