From 818427c5e93870c5f568ff81b2ac48ddb013f84a Mon Sep 17 00:00:00 2001 From: tb Date: Fri, 14 Jan 2022 08:40:57 +0000 Subject: [PATCH] Implement new-style OpenSSL BIO callbacks This provides support for new-style BIO callbacks in BIO_{read,write,gets,puts}() and a helper function to work out whether it should call the new or the old style callback. It also adds a few typedefs and minor code cleanup as well as the BIO_{get,set}_callback_ex() from jsing, ok tb --- lib/libcrypto/asn1/bio_asn1.c | 6 +- lib/libcrypto/bio/bf_buff.c | 6 +- lib/libcrypto/bio/bf_lbuf.c | 6 +- lib/libcrypto/bio/bf_nbio.c | 6 +- lib/libcrypto/bio/bf_null.c | 6 +- lib/libcrypto/bio/bio.h | 29 ++-- lib/libcrypto/bio/bio_err.c | 3 +- lib/libcrypto/bio/bio_lib.c | 288 ++++++++++++++++++++++++---------- lib/libcrypto/bio/bio_local.h | 8 +- lib/libcrypto/bio/bio_meth.c | 8 +- lib/libcrypto/bio/bss_conn.c | 21 +-- lib/libcrypto/comp/c_zlib.c | 6 +- lib/libcrypto/evp/bio_b64.c | 6 +- lib/libcrypto/evp/bio_enc.c | 6 +- lib/libcrypto/evp/bio_md.c | 6 +- 15 files changed, 266 insertions(+), 145 deletions(-) diff --git a/lib/libcrypto/asn1/bio_asn1.c b/lib/libcrypto/asn1/bio_asn1.c index 6bc42009f7e..9017786f1f9 100644 --- a/lib/libcrypto/asn1/bio_asn1.c +++ b/lib/libcrypto/asn1/bio_asn1.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bio_asn1.c,v 1.16 2022/01/07 09:02:17 tb Exp $ */ +/* $OpenBSD: bio_asn1.c,v 1.17 2022/01/14 08:40:57 tb Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project. */ @@ -118,7 +118,7 @@ static int asn1_bio_gets(BIO *h, char *str, int size); static long asn1_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int asn1_bio_new(BIO *h); static int asn1_bio_free(BIO *data); -static long asn1_bio_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp); +static long asn1_bio_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx, asn1_ps_func *cleanup, asn1_bio_state_t next); @@ -346,7 +346,7 @@ asn1_bio_gets(BIO *b, char *str, int size) } static long -asn1_bio_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) +asn1_bio_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) { if (b->next_bio == NULL) return (0); diff --git a/lib/libcrypto/bio/bf_buff.c b/lib/libcrypto/bio/bf_buff.c index 42414bb51a0..aa079c5f9e7 100644 --- a/lib/libcrypto/bio/bf_buff.c +++ b/lib/libcrypto/bio/bf_buff.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bf_buff.c,v 1.26 2022/01/07 09:02:17 tb Exp $ */ +/* $OpenBSD: bf_buff.c,v 1.27 2022/01/14 08:40:57 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -72,7 +72,7 @@ static int buffer_gets(BIO *h, char *str, int size); static long buffer_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int buffer_new(BIO *h); static int buffer_free(BIO *data); -static long buffer_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp); +static long buffer_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); #define DEFAULT_BUFFER_SIZE 4096 static const BIO_METHOD methods_buffer = { @@ -452,7 +452,7 @@ malloc_error: } static long -buffer_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) +buffer_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) { long ret = 1; diff --git a/lib/libcrypto/bio/bf_lbuf.c b/lib/libcrypto/bio/bf_lbuf.c index 5d9ec0f0254..d65150881c6 100644 --- a/lib/libcrypto/bio/bf_lbuf.c +++ b/lib/libcrypto/bio/bf_lbuf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bf_lbuf.c,v 1.14 2017/01/29 17:49:22 beck Exp $ */ +/* $OpenBSD: bf_lbuf.c,v 1.15 2022/01/14 08:40:57 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -69,7 +69,7 @@ static int linebuffer_gets(BIO *h, char *str, int size); static long linebuffer_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int linebuffer_new(BIO *h); static int linebuffer_free(BIO *data); -static long linebuffer_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp); +static long linebuffer_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); /* A 10k maximum should be enough for most purposes */ #define DEFAULT_LINEBUFFER_SIZE 1024*10 @@ -348,7 +348,7 @@ malloc_error: } static long -linebuffer_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) +linebuffer_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) { long ret = 1; diff --git a/lib/libcrypto/bio/bf_nbio.c b/lib/libcrypto/bio/bf_nbio.c index c0a5ab2bcb3..086479ec4c0 100644 --- a/lib/libcrypto/bio/bf_nbio.c +++ b/lib/libcrypto/bio/bf_nbio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bf_nbio.c,v 1.21 2022/01/07 09:02:17 tb Exp $ */ +/* $OpenBSD: bf_nbio.c,v 1.22 2022/01/14 08:40:57 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -74,7 +74,7 @@ static int nbiof_gets(BIO *h, char *str, int size); static long nbiof_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int nbiof_new(BIO *h); static int nbiof_free(BIO *data); -static long nbiof_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp); +static long nbiof_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); typedef struct nbio_test_st { /* only set if we sent a 'should retry' error */ @@ -223,7 +223,7 @@ nbiof_ctrl(BIO *b, int cmd, long num, void *ptr) } static long -nbiof_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) +nbiof_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) { long ret = 1; diff --git a/lib/libcrypto/bio/bf_null.c b/lib/libcrypto/bio/bf_null.c index 1a935cf26bd..129def8c99a 100644 --- a/lib/libcrypto/bio/bf_null.c +++ b/lib/libcrypto/bio/bf_null.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bf_null.c,v 1.13 2022/01/07 09:02:17 tb Exp $ */ +/* $OpenBSD: bf_null.c,v 1.14 2022/01/14 08:40:57 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -73,7 +73,7 @@ static int nullf_gets(BIO *h, char *str, int size); static long nullf_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int nullf_new(BIO *h); static int nullf_free(BIO *data); -static long nullf_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp); +static long nullf_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); static const BIO_METHOD methods_nullf = { .type = BIO_TYPE_NULL_FILTER, @@ -167,7 +167,7 @@ nullf_ctrl(BIO *b, int cmd, long num, void *ptr) } static long -nullf_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) +nullf_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) { long ret = 1; diff --git a/lib/libcrypto/bio/bio.h b/lib/libcrypto/bio/bio.h index 8feb98d4578..679e88a3bc8 100644 --- a/lib/libcrypto/bio/bio.h +++ b/lib/libcrypto/bio/bio.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bio.h,v 1.53 2022/01/14 08:18:55 tb Exp $ */ +/* $OpenBSD: bio.h,v 1.54 2022/01/14 08:40:57 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -250,21 +250,30 @@ void BIO_clear_flags(BIO *b, int flags); #define BIO_CB_GETS 0x05 #define BIO_CB_CTRL 0x06 -/* The callback is called before and after the underling operation, - * The BIO_CB_RETURN flag indicates if it is after the call */ +/* + * The callback is called before and after the underling operation, + * the BIO_CB_RETURN flag indicates if it is after the call. + */ #define BIO_CB_RETURN 0x80 #define BIO_CB_return(a) ((a)|BIO_CB_RETURN)) #define BIO_cb_pre(a) (!((a)&BIO_CB_RETURN)) #define BIO_cb_post(a) ((a)&BIO_CB_RETURN) -long (*BIO_get_callback(const BIO *b))(struct bio_st *, int, const char *, - int, long, long); -void BIO_set_callback(BIO *b, - long (*callback)(struct bio_st *, int, const char *, int, long, long)); +typedef long (*BIO_callback_fn)(BIO *b, int oper, const char *argp, int argi, + long argl, long ret); +typedef long (*BIO_callback_fn_ex)(BIO *b, int oper, const char *argp, + size_t len, int argi, long argl, int ret, size_t *processed); + +BIO_callback_fn BIO_get_callback(const BIO *b); +void BIO_set_callback(BIO *b, BIO_callback_fn callback); + +BIO_callback_fn_ex BIO_get_callback_ex(const BIO *b); +void BIO_set_callback_ex(BIO *b, BIO_callback_fn_ex callback); + char *BIO_get_callback_arg(const BIO *b); void BIO_set_callback_arg(BIO *b, char *arg); -const char * BIO_method_name(const BIO *b); +const char *BIO_method_name(const BIO *b); int BIO_method_type(const BIO *b); typedef void bio_info_cb(struct bio_st *, int, const char *, int, long, long); @@ -563,8 +572,7 @@ int BIO_write(BIO *b, const void *data, int len) int BIO_puts(BIO *bp, const char *buf); int BIO_indent(BIO *b, int indent, int max); long BIO_ctrl(BIO *bp, int cmd, long larg, void *parg); -long BIO_callback_ctrl(BIO *b, int cmd, - void (*fp)(struct bio_st *, int, const char *, int, long, long)); +long BIO_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp); char * BIO_ptr_ctrl(BIO *bp, int cmd, long larg); long BIO_int_ctrl(BIO *bp, int cmd, long larg, int iarg); BIO * BIO_push(BIO *b, BIO *append); @@ -732,6 +740,7 @@ void ERR_load_BIO_strings(void); #define BIO_R_INVALID_PORT_NUMBER 129 #define BIO_R_IN_USE 123 #define BIO_R_KEEPALIVE 109 +#define BIO_R_LENGTH_TOO_LONG 130 #define BIO_R_NBIO_CONNECT_ERROR 110 #define BIO_R_NO_ACCEPT_PORT_SPECIFIED 111 #define BIO_R_NO_HOSTNAME_SPECIFIED 112 diff --git a/lib/libcrypto/bio/bio_err.c b/lib/libcrypto/bio/bio_err.c index 2920e321034..cda693d0362 100644 --- a/lib/libcrypto/bio/bio_err.c +++ b/lib/libcrypto/bio/bio_err.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bio_err.c,v 1.17 2017/01/29 17:49:22 beck Exp $ */ +/* $OpenBSD: bio_err.c,v 1.18 2022/01/14 08:40:57 tb Exp $ */ /* ==================================================================== * Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved. * @@ -92,6 +92,7 @@ static ERR_STRING_DATA BIO_str_reasons[] = { {ERR_REASON(BIO_R_INVALID_PORT_NUMBER) , "invalid port number"}, {ERR_REASON(BIO_R_IN_USE) , "in use"}, {ERR_REASON(BIO_R_KEEPALIVE) , "keepalive"}, + {ERR_REASON(BIO_R_LENGTH_TOO_LONG) , "too long"}, {ERR_REASON(BIO_R_NBIO_CONNECT_ERROR) , "nbio connect error"}, {ERR_REASON(BIO_R_NO_ACCEPT_PORT_SPECIFIED), "no accept port specified"}, {ERR_REASON(BIO_R_NO_HOSTNAME_SPECIFIED) , "no hostname specified"}, diff --git a/lib/libcrypto/bio/bio_lib.c b/lib/libcrypto/bio/bio_lib.c index 59c13172964..0b6c9ecac0d 100644 --- a/lib/libcrypto/bio/bio_lib.c +++ b/lib/libcrypto/bio/bio_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bio_lib.c,v 1.34 2022/01/07 09:02:17 tb Exp $ */ +/* $OpenBSD: bio_lib.c,v 1.35 2022/01/14 08:40:57 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -57,6 +57,7 @@ */ #include +#include #include #include @@ -66,6 +67,55 @@ #include "bio_local.h" +/* + * Helper function to work out whether to call the new style callback or the old + * one, and translate between the two. + * + * This has a long return type for consistency with the old callback. Similarly + * for the "long" used for "inret" + */ +static long +bio_call_callback(BIO *b, int oper, const char *argp, size_t len, int argi, + long argl, long inret, size_t *processed) +{ + long ret; + int bareoper; + + if (b->callback_ex != NULL) + return b->callback_ex(b, oper, argp, len, argi, argl, inret, + processed); + + /* + * We have an old style callback, so we will have to do nasty casts and + * check for overflows. + */ + + bareoper = oper & ~BIO_CB_RETURN; + + if (bareoper == BIO_CB_READ || bareoper == BIO_CB_WRITE || + bareoper == BIO_CB_GETS) { + /* In this case len is set and should be used instead of argi. */ + if (len > INT_MAX) + return -1; + argi = (int)len; + } + + if (inret > 0 && (oper & BIO_CB_RETURN) && bareoper != BIO_CB_CTRL) { + if (*processed > INT_MAX) + return -1; + inret = *processed; + } + + ret = b->callback(b, oper, argp, argi, argl, inret); + + if (ret > 0 && (oper & BIO_CB_RETURN) && bareoper != BIO_CB_CTRL) { + *processed = (size_t)ret; + ret = 1; + } + + return ret; +} + int BIO_get_new_index(void) { @@ -85,6 +135,7 @@ BIO_new(const BIO_METHOD *method) { BIO *ret = NULL; + /* XXX calloc */ ret = malloc(sizeof(BIO)); if (ret == NULL) { BIOerror(ERR_R_MALLOC_FAILURE); @@ -102,6 +153,7 @@ BIO_set(BIO *bio, const BIO_METHOD *method) { bio->method = method; bio->callback = NULL; + bio->callback_ex = NULL; bio->cb_arg = NULL; bio->init = 0; bio->shutdown = 1; @@ -115,29 +167,32 @@ BIO_set(BIO *bio, const BIO_METHOD *method) bio->num_read = 0L; bio->num_write = 0L; CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data); - if (method->create != NULL) + if (method->create != NULL) { if (!method->create(bio)) { CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data); return (0); } + } return (1); } int BIO_free(BIO *a) { - int i; + int ret; if (a == NULL) return (0); - i = CRYPTO_add(&a->references, -1, CRYPTO_LOCK_BIO); - if (i > 0) + if (CRYPTO_add(&a->references, -1, CRYPTO_LOCK_BIO) > 0) return (1); - if ((a->callback != NULL) && - ((i = (int)a->callback(a, BIO_CB_FREE, NULL, 0, 0L, 1L)) <= 0)) - return (i); + + if (a->callback != NULL || a->callback_ex != NULL) { + if ((ret = (int)bio_call_callback(a, BIO_CB_FREE, NULL, 0, 0, + 0L, 1L, NULL)) <= 0) + return (ret); + } CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, a, &a->ex_data); @@ -214,20 +269,30 @@ BIO_set_flags(BIO *b, int flags) b->flags |= flags; } -long -(*BIO_get_callback(const BIO *b))(struct bio_st *, int, const char *, int, - long, long) +BIO_callback_fn +BIO_get_callback(const BIO *b) { return b->callback; } void -BIO_set_callback(BIO *b, long (*cb)(struct bio_st *, int, const char *, int, - long, long)) +BIO_set_callback(BIO *b, BIO_callback_fn cb) { b->callback = cb; } +BIO_callback_fn_ex +BIO_get_callback_ex(const BIO *b) +{ + return b->callback_ex; +} + +void +BIO_set_callback_ex(BIO *b, BIO_callback_fn_ex cb) +{ + b->callback_ex = cb; +} + void BIO_set_callback_arg(BIO *b, char *arg) { @@ -255,8 +320,8 @@ BIO_method_type(const BIO *b) int BIO_read(BIO *b, void *out, int outl) { - int i; - long (*cb)(BIO *, int, const char *, int, long, long); + size_t readbytes = 0; + int ret; if (b == NULL) return (0); @@ -269,33 +334,44 @@ BIO_read(BIO *b, void *out, int outl) return (-2); } - cb = b->callback; - if ((cb != NULL) && - ((i = (int)cb(b, BIO_CB_READ, out, outl, 0L, 1L)) <= 0)) - return (i); + if (b->callback != NULL || b->callback_ex != NULL) { + if ((ret = (int)bio_call_callback(b, BIO_CB_READ, out, outl, 0, + 0L, 1L, NULL)) <= 0) + return (ret); + } if (!b->init) { BIOerror(BIO_R_UNINITIALIZED); return (-2); } - i = b->method->bread(b, out, outl); + if ((ret = b->method->bread(b, out, outl)) > 0) + readbytes = (size_t)ret; - if (i > 0) - b->num_read += (unsigned long)i; + b->num_read += readbytes; - if (cb != NULL) - i = (int)cb(b, BIO_CB_READ|BIO_CB_RETURN, out, outl, - 0L, (long)i); + if (b->callback != NULL || b->callback_ex != NULL) { + ret = (int)bio_call_callback(b, BIO_CB_READ | BIO_CB_RETURN, + out, outl, 0, 0L, (ret > 0) ? 1 : ret, &readbytes); + } - return (i); + if (ret > 0) { + if (readbytes > INT_MAX) { + BIOerror(BIO_R_LENGTH_TOO_LONG); + ret = -1; + } else { + ret = (int)readbytes; + } + } + + return (ret); } int BIO_write(BIO *b, const void *in, int inl) { - int i; - long (*cb)(BIO *, int, const char *, int, long, long); + size_t writebytes = 0; + int ret; if (b == NULL) return (0); @@ -308,86 +384,123 @@ BIO_write(BIO *b, const void *in, int inl) return (-2); } - cb = b->callback; - if ((cb != NULL) && - ((i = (int)cb(b, BIO_CB_WRITE, in, inl, 0L, 1L)) <= 0)) - return (i); + if (b->callback != NULL || b->callback_ex != NULL) { + if ((ret = (int)bio_call_callback(b, BIO_CB_WRITE, in, inl, 0, + 0L, 1L, NULL)) <= 0) + return (ret); + } if (!b->init) { BIOerror(BIO_R_UNINITIALIZED); return (-2); } - i = b->method->bwrite(b, in, inl); + if ((ret = b->method->bwrite(b, in, inl)) > 0) + writebytes = ret; + + b->num_write += writebytes; + + if (b->callback != NULL || b->callback_ex != NULL) { + ret = (int)bio_call_callback(b, BIO_CB_WRITE | BIO_CB_RETURN, + in, inl, 0, 0L, (ret > 0) ? 1 : ret, &writebytes); + } - if (i > 0) - b->num_write += (unsigned long)i; + if (ret > 0) { + if (writebytes > INT_MAX) { + BIOerror(BIO_R_LENGTH_TOO_LONG); + ret = -1; + } else { + ret = (int)writebytes; + } + } - if (cb != NULL) - i = (int)cb(b, BIO_CB_WRITE|BIO_CB_RETURN, in, inl, - 0L, (long)i); - return (i); + return (ret); } int BIO_puts(BIO *b, const char *in) { - int i; - long (*cb)(BIO *, int, const char *, int, long, long); + size_t writebytes = 0; + int ret; - if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL)) { + if (b == NULL || b->method == NULL || b->method->bputs == NULL) { BIOerror(BIO_R_UNSUPPORTED_METHOD); return (-2); } - cb = b->callback; - - if ((cb != NULL) && - ((i = (int)cb(b, BIO_CB_PUTS, in, 0, 0L, 1L)) <= 0)) - return (i); + if (b->callback != NULL || b->callback_ex != NULL) { + if ((ret = (int)bio_call_callback(b, BIO_CB_PUTS, in, 0, 0, 0L, + 1L, NULL)) <= 0) + return (ret); + } if (!b->init) { BIOerror(BIO_R_UNINITIALIZED); return (-2); } - i = b->method->bputs(b, in); + if ((ret = b->method->bputs(b, in)) > 0) + writebytes = ret; - if (i > 0) - b->num_write += (unsigned long)i; + b->num_write += writebytes; - if (cb != NULL) - i = (int)cb(b, BIO_CB_PUTS|BIO_CB_RETURN, in, 0, 0L, (long)i); - return (i); + if (b->callback != NULL || b->callback_ex != NULL) { + ret = (int)bio_call_callback(b, BIO_CB_PUTS | BIO_CB_RETURN, + in, 0, 0, 0L, (ret > 0) ? 1 : ret, &writebytes); + } + + if (ret > 0) { + if (writebytes > INT_MAX) { + BIOerror(BIO_R_LENGTH_TOO_LONG); + ret = -1; + } else { + ret = (int)writebytes; + } + } + + return (ret); } int BIO_gets(BIO *b, char *in, int inl) { - int i; - long (*cb)(BIO *, int, const char *, int, long, long); + size_t readbytes; + int ret; - if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL)) { + if (b == NULL || b->method == NULL || b->method->bgets == NULL) { BIOerror(BIO_R_UNSUPPORTED_METHOD); return (-2); } - cb = b->callback; - - if ((cb != NULL) && - ((i = (int)cb(b, BIO_CB_GETS, in, inl, 0L, 1L)) <= 0)) - return (i); + if (b->callback != NULL || b->callback_ex != NULL) { + if ((ret = (int)bio_call_callback(b, BIO_CB_GETS, in, inl, 0, 0L, + 1, NULL)) <= 0) + return (ret); + } if (!b->init) { BIOerror(BIO_R_UNINITIALIZED); return (-2); } - i = b->method->bgets(b, in, inl); + if ((ret = b->method->bgets(b, in, inl)) > 0) + readbytes = ret; + + if (b->callback != NULL || b->callback_ex != NULL) { + ret = (int)bio_call_callback(b, BIO_CB_GETS | BIO_CB_RETURN, in, + inl, 0, 0L, (ret > 0) ? 1 : ret, &readbytes); + } + + if (ret > 0) { + if (readbytes > INT_MAX) { + BIOerror(BIO_R_LENGTH_TOO_LONG); + ret = -1; + } else { + ret = (int)readbytes; + } + } - if (cb != NULL) - i = (int)cb(b, BIO_CB_GETS|BIO_CB_RETURN, in, inl, 0L, (long)i); - return (i); + return (ret); } int @@ -427,54 +540,58 @@ long BIO_ctrl(BIO *b, int cmd, long larg, void *parg) { long ret; - long (*cb)(BIO *, int, const char *, int, long, long); if (b == NULL) return (0); - if ((b->method == NULL) || (b->method->ctrl == NULL)) { + if (b->method == NULL || b->method->ctrl == NULL) { BIOerror(BIO_R_UNSUPPORTED_METHOD); return (-2); } - cb = b->callback; - - if ((cb != NULL) && - ((ret = cb(b, BIO_CB_CTRL, parg, cmd, larg, 1L)) <= 0)) - return (ret); + if (b->callback != NULL || b->callback_ex != NULL) { + if ((ret = bio_call_callback(b, BIO_CB_CTRL, parg, 0, cmd, larg, + 1L, NULL)) <= 0) + return (ret); + } ret = b->method->ctrl(b, cmd, larg, parg); - if (cb != NULL) - ret = cb(b, BIO_CB_CTRL|BIO_CB_RETURN, parg, cmd, larg, ret); + if (b->callback != NULL || b->callback_ex != NULL) { + ret = bio_call_callback(b, BIO_CB_CTRL | BIO_CB_RETURN, parg, 0, + cmd, larg, ret, NULL); + } + return (ret); } long -BIO_callback_ctrl(BIO *b, int cmd, - void (*fp)(struct bio_st *, int, const char *, int, long, long)) +BIO_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) { long ret; - long (*cb)(BIO *, int, const char *, int, long, long); if (b == NULL) return (0); - if ((b->method == NULL) || (b->method->callback_ctrl == NULL)) { + if (b->method == NULL || b->method->callback_ctrl == NULL || + cmd != BIO_CTRL_SET_CALLBACK) { BIOerror(BIO_R_UNSUPPORTED_METHOD); return (-2); } - cb = b->callback; - - if ((cb != NULL) && - ((ret = cb(b, BIO_CB_CTRL, (void *)&fp, cmd, 0, 1L)) <= 0)) - return (ret); + if (b->callback != NULL || b->callback_ex != NULL) { + if ((ret = bio_call_callback(b, BIO_CB_CTRL, (void *)&fp, 0, + cmd, 0, 1L, NULL)) <= 0) + return (ret); + } ret = b->method->callback_ctrl(b, cmd, fp); - if (cb != NULL) - ret = cb(b, BIO_CB_CTRL|BIO_CB_RETURN, (void *)&fp, cmd, 0, ret); + if (b->callback != NULL || b->callback_ex != NULL) { + ret = bio_call_callback(b, BIO_CB_CTRL | BIO_CB_RETURN, + (void *)&fp, 0, cmd, 0, ret, NULL); + } + return (ret); } @@ -628,6 +745,7 @@ BIO_dup_chain(BIO *in) if ((new_bio = BIO_new(bio->method)) == NULL) goto err; new_bio->callback = bio->callback; + new_bio->callback_ex = bio->callback_ex; new_bio->cb_arg = bio->cb_arg; new_bio->init = bio->init; new_bio->shutdown = bio->shutdown; diff --git a/lib/libcrypto/bio/bio_local.h b/lib/libcrypto/bio/bio_local.h index 62a9793d008..7e1885f393e 100644 --- a/lib/libcrypto/bio/bio_local.h +++ b/lib/libcrypto/bio/bio_local.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bio_local.h,v 1.2 2022/01/14 08:18:55 tb Exp $ */ +/* $OpenBSD: bio_local.h,v 1.3 2022/01/14 08:40:57 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -71,13 +71,13 @@ struct bio_method_st { long (*ctrl)(BIO *, int, long, void *); int (*create)(BIO *); int (*destroy)(BIO *); - long (*callback_ctrl)(BIO *, int, bio_info_cb *); + long (*callback_ctrl)(BIO *, int, BIO_info_cb *); } /* BIO_METHOD */; struct bio_st { const BIO_METHOD *method; - /* bio, mode, argp, argi, argl, ret */ - long (*callback)(struct bio_st *, int, const char *, int, long, long); + BIO_callback_fn callback; + BIO_callback_fn_ex callback_ex; char *cb_arg; /* first argument for the callback */ int init; diff --git a/lib/libcrypto/bio/bio_meth.c b/lib/libcrypto/bio/bio_meth.c index b9c07d5111c..d7d100df951 100644 --- a/lib/libcrypto/bio/bio_meth.c +++ b/lib/libcrypto/bio/bio_meth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bio_meth.c,v 1.7 2022/01/07 09:02:17 tb Exp $ */ +/* $OpenBSD: bio_meth.c,v 1.8 2022/01/14 08:40:57 tb Exp $ */ /* * Copyright (c) 2018 Theo Buehler * @@ -135,15 +135,13 @@ BIO_meth_set_destroy(BIO_METHOD *biom, int (*destroy)(BIO *)) long (*BIO_meth_get_callback_ctrl(const BIO_METHOD *biom))(BIO *, int, BIO_info_cb *) { - return - (long (*)(BIO *, int, BIO_info_cb *))biom->callback_ctrl; /* XXX */ + return biom->callback_ctrl; } int BIO_meth_set_callback_ctrl(BIO_METHOD *biom, long (*callback_ctrl)(BIO *, int, BIO_info_cb *)) { - biom->callback_ctrl = - (long (*)(BIO *, int, bio_info_cb *))callback_ctrl; /* XXX */ + biom->callback_ctrl = callback_ctrl; return 1; } diff --git a/lib/libcrypto/bio/bss_conn.c b/lib/libcrypto/bio/bss_conn.c index 8ed8d2076d6..8e30bccd512 100644 --- a/lib/libcrypto/bio/bss_conn.c +++ b/lib/libcrypto/bio/bss_conn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bss_conn.c,v 1.36 2022/01/07 09:02:17 tb Exp $ */ +/* $OpenBSD: bss_conn.c,v 1.37 2022/01/14 08:40:57 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -92,7 +92,7 @@ typedef struct bio_connect_st { /* called when the connection is initially made * callback(BIO,state,ret); The callback should return * 'ret'. state is for compatibility with the ssl info_callback */ - int (*info_callback)(const BIO *bio, int state, int ret); + BIO_info_cb *info_callback; } BIO_CONNECT; static int conn_write(BIO *h, const char *buf, int num); @@ -101,7 +101,7 @@ static int conn_puts(BIO *h, const char *str); static long conn_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int conn_new(BIO *h); static int conn_free(BIO *data); -static long conn_callback_ctrl(BIO *h, int cmd, bio_info_cb *); +static long conn_callback_ctrl(BIO *h, int cmd, BIO_info_cb *); static int conn_state(BIO *b, BIO_CONNECT *c); static void conn_close_socket(BIO *data); @@ -126,7 +126,7 @@ conn_state(BIO *b, BIO_CONNECT *c) int ret = -1, i; unsigned long l; char *p, *q; - int (*cb)(const BIO *, int, int) = NULL; + BIO_info_cb *cb = NULL; if (c->info_callback != NULL) cb = c->info_callback; @@ -523,9 +523,7 @@ conn_ctrl(BIO *b, int cmd, long num, void *ptr) BIO_set_conn_hostname(dbio, data->param_hostname); BIO_set_nbio(dbio, data->nbio); - /* FIXME: the cast of the function seems unlikely to be a good idea */ - (void)BIO_set_info_callback(dbio, - (bio_info_cb *)data->info_callback); + (void)BIO_set_info_callback(dbio, data->info_callback); } break; case BIO_CTRL_SET_CALLBACK: @@ -540,9 +538,8 @@ conn_ctrl(BIO *b, int cmd, long num, void *ptr) break; case BIO_CTRL_GET_CALLBACK: { - int (**fptr)(const BIO *bio, int state, int xret); + BIO_info_cb **fptr = ptr; - fptr = (int (**)(const BIO *bio, int state, int xret))ptr; *fptr = data->info_callback; } break; @@ -554,7 +551,7 @@ conn_ctrl(BIO *b, int cmd, long num, void *ptr) } static long -conn_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) +conn_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) { long ret = 1; BIO_CONNECT *data; @@ -563,9 +560,7 @@ conn_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) switch (cmd) { case BIO_CTRL_SET_CALLBACK: - { - data->info_callback = (int (*)(const struct bio_st *, int, int))fp; - } + data->info_callback = (BIO_info_cb *)fp; break; default: ret = 0; diff --git a/lib/libcrypto/comp/c_zlib.c b/lib/libcrypto/comp/c_zlib.c index 4c527d57de3..bdcd7e0f355 100644 --- a/lib/libcrypto/comp/c_zlib.c +++ b/lib/libcrypto/comp/c_zlib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: c_zlib.c,v 1.21 2022/01/09 23:50:10 tb Exp $ */ +/* $OpenBSD: c_zlib.c,v 1.22 2022/01/14 08:40:57 tb Exp $ */ #include #include #include @@ -234,7 +234,7 @@ static int bio_zlib_free(BIO *bi); static int bio_zlib_read(BIO *b, char *out, int outl); static int bio_zlib_write(BIO *b, const char *in, int inl); static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr); -static long bio_zlib_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp); +static long bio_zlib_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp); static BIO_METHOD bio_meth_zlib = { .type = BIO_TYPE_COMP, @@ -555,7 +555,7 @@ bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr) static long -bio_zlib_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) +bio_zlib_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) { if (!b->next_bio) return 0; diff --git a/lib/libcrypto/evp/bio_b64.c b/lib/libcrypto/evp/bio_b64.c index c1ec25d9c4d..b61a342a3e0 100644 --- a/lib/libcrypto/evp/bio_b64.c +++ b/lib/libcrypto/evp/bio_b64.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bio_b64.c,v 1.24 2022/01/07 09:02:18 tb Exp $ */ +/* $OpenBSD: bio_b64.c,v 1.25 2022/01/14 08:40:57 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -73,7 +73,7 @@ static int b64_puts(BIO *h, const char *str); static long b64_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int b64_new(BIO *h); static int b64_free(BIO *data); -static long b64_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp); +static long b64_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); #define B64_BLOCK_SIZE 1024 #define B64_BLOCK_SIZE2 768 #define B64_NONE 0 @@ -550,7 +550,7 @@ again: } static long -b64_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) +b64_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) { long ret = 1; diff --git a/lib/libcrypto/evp/bio_enc.c b/lib/libcrypto/evp/bio_enc.c index 6ab07e13d94..2a0f76fcbe4 100644 --- a/lib/libcrypto/evp/bio_enc.c +++ b/lib/libcrypto/evp/bio_enc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bio_enc.c,v 1.25 2022/01/07 09:02:18 tb Exp $ */ +/* $OpenBSD: bio_enc.c,v 1.26 2022/01/14 08:40:57 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -73,7 +73,7 @@ static int enc_read(BIO *h, char *buf, int size); static long enc_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int enc_new(BIO *h); static int enc_free(BIO *data); -static long enc_callback_ctrl(BIO *h, int cmd, bio_info_cb *fps); +static long enc_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fps); #define ENC_BLOCK_SIZE (1024*4) #define BUF_OFFSET (EVP_MAX_BLOCK_LENGTH*2) @@ -373,7 +373,7 @@ again: } static long -enc_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) +enc_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) { long ret = 1; diff --git a/lib/libcrypto/evp/bio_md.c b/lib/libcrypto/evp/bio_md.c index a83088a9637..4ae5f1f496b 100644 --- a/lib/libcrypto/evp/bio_md.c +++ b/lib/libcrypto/evp/bio_md.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bio_md.c,v 1.17 2022/01/07 09:02:18 tb Exp $ */ +/* $OpenBSD: bio_md.c,v 1.18 2022/01/14 08:40:57 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -75,7 +75,7 @@ static int md_gets(BIO *h, char *str, int size); static long md_ctrl(BIO *h, int cmd, long arg1, void *arg2); static int md_new(BIO *h); static int md_free(BIO *data); -static long md_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp); +static long md_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); static const BIO_METHOD methods_md = { .type = BIO_TYPE_MD, @@ -241,7 +241,7 @@ md_ctrl(BIO *b, int cmd, long num, void *ptr) } static long -md_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) +md_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) { long ret = 1; -- 2.20.1