Implement new-style OpenSSL BIO callbacks
authortb <tb@openbsd.org>
Fri, 14 Jan 2022 08:40:57 +0000 (08:40 +0000)
committertb <tb@openbsd.org>
Fri, 14 Jan 2022 08:40:57 +0000 (08:40 +0000)
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

15 files changed:
lib/libcrypto/asn1/bio_asn1.c
lib/libcrypto/bio/bf_buff.c
lib/libcrypto/bio/bf_lbuf.c
lib/libcrypto/bio/bf_nbio.c
lib/libcrypto/bio/bf_null.c
lib/libcrypto/bio/bio.h
lib/libcrypto/bio/bio_err.c
lib/libcrypto/bio/bio_lib.c
lib/libcrypto/bio/bio_local.h
lib/libcrypto/bio/bio_meth.c
lib/libcrypto/bio/bss_conn.c
lib/libcrypto/comp/c_zlib.c
lib/libcrypto/evp/bio_b64.c
lib/libcrypto/evp/bio_enc.c
lib/libcrypto/evp/bio_md.c

index 6bc4200..9017786 100644 (file)
@@ -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);
index 42414bb..aa079c5 100644 (file)
@@ -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;
 
index 5d9ec0f..d651508 100644 (file)
@@ -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;
 
index c0a5ab2..086479e 100644 (file)
@@ -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;
 
index 1a935cf..129def8 100644 (file)
@@ -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;
 
index 8feb98d..679e88a 100644 (file)
@@ -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
index 2920e32..cda693d 100644 (file)
@@ -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"},
index 59c1317..0b6c9ec 100644 (file)
@@ -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 <errno.h>
+#include <limits.h>
 #include <stdio.h>
 
 #include <openssl/bio.h>
 
 #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;
index 62a9793..7e1885f 100644 (file)
@@ -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;
index b9c07d5..d7d100d 100644 (file)
@@ -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 <tb@openbsd.org>
  *
@@ -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;
 }
index 8ed8d20..8e30bcc 100644 (file)
@@ -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;
index 4c527d5..bdcd7e0 100644 (file)
@@ -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 <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -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;
index c1ec25d..b61a342 100644 (file)
@@ -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;
 
index 6ab07e1..2a0f76f 100644 (file)
@@ -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;
 
index a83088a..4ae5f1f 100644 (file)
@@ -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;