25RCSID(
"$Id: 0dbce7c55c8e394c112e091ee1ef2aa172b823cc $")
29#include <freeradius-devel/util/atexit.h>
37struct fr_tls_bio_dbuff_s {
41 fr_dbuff_uctx_talloc_t tctx;
57static int tls_bio_dbuff_datagram_push(fr_tls_bio_dbuff_t *bd,
size_t len)
59 if (!bd->datagram)
return 0;
64 fr_assert((bd->datagram_used > 0) || (bd->datagram_head == 0));
66 if ((bd->datagram_head + bd->datagram_used) == FR_TLS_MAX_DATAGRAMS) {
67 if (bd->datagram_head == 0)
return -1;
69 memmove(&bd->datagram[0], &bd->datagram[bd->datagram_head],
70 bd->datagram_used *
sizeof(bd->datagram[0]));
71 bd->datagram_head = 0;
74 bd->datagram[bd->datagram_head + bd->datagram_used] =
len;
82static BIO_METHOD *tls_bio_talloc_meth;
94static int _tls_bio_talloc_write_cb(BIO *bio,
char const *
in,
int len)
96 fr_tls_bio_dbuff_t *bd = talloc_get_type_abort(BIO_get_data(bio), fr_tls_bio_dbuff_t);
108 if (!bd->datagram)
return (
int) slen;
118 if (tls_bio_dbuff_datagram_push(bd, (
size_t)
len) < 0)
return -1;
128static int _tls_bio_talloc_puts_cb(BIO *bio,
char const *
in)
130 return _tls_bio_talloc_write_cb(bio,
in, strlen(
in));
140static int _tls_bio_talloc_read_cb(BIO *bio,
char *buf,
int size)
142 fr_tls_bio_dbuff_t *bd = talloc_get_type_abort(BIO_get_data(bio), fr_tls_bio_dbuff_t);
152 BIO_set_retry_read(bio);
155 BIO_clear_retry_flags(bio);
158 if (to_copy > (
size_t)size) to_copy = (
size_t)size;
181static int _tls_bio_talloc_gets_cb(BIO *bio,
char *buf,
int size)
183 fr_tls_bio_dbuff_t *bd = talloc_get_type_abort(BIO_get_data(bio), fr_tls_bio_dbuff_t);
210 if (to_copy >= (
size_t)size) to_copy = (
size_t)size - 1;
231static inline CC_HINT(always_inline)
void tls_bio_dbuff_detach(fr_tls_bio_dbuff_t *bd)
233 bd->dbuff_in.buff = NULL;
234 bd->dbuff_out.buff = NULL;
243uint8_t *fr_tls_bio_dbuff_finalise(fr_tls_bio_dbuff_t *bd)
248 if (
unlikely(!bd->dbuff_in.buff))
return NULL;
252 buff = bd->dbuff_in.buff;
253 tls_bio_dbuff_detach(bd);
263char *fr_tls_bio_dbuff_finalise_bstr(fr_tls_bio_dbuff_t *bd)
268 if (
unlikely(!bd->dbuff_in.buff))
return NULL;
273 buff = bd->dbuff_in.buff;
274 tls_bio_dbuff_detach(bd);
275 talloc_set_type(
buff,
char);
288void fr_tls_bio_dbuff_reset(fr_tls_bio_dbuff_t *bd)
292 bd->datagram_head = bd->datagram_used = 0;
314int fr_tls_bio_dbuff_datagram_init(fr_tls_bio_dbuff_t *bd)
316 if (bd->datagram)
return 0;
318 bd->datagram = talloc_array(bd,
size_t, FR_TLS_MAX_DATAGRAMS);
319 if (
unlikely(!bd->datagram))
return -1;
326 fr_assert((bd->datagram_head == 0) && (bd->datagram_used == 0));
338size_t fr_tls_bio_dbuff_datagram_len(fr_tls_bio_dbuff_t *bd)
340 if (!bd->datagram || (bd->datagram_used == 0))
return 0;
342 return bd->datagram[bd->datagram_head];
349void fr_tls_bio_dbuff_datagram_sent(fr_tls_bio_dbuff_t *bd)
351 if (!bd->datagram || (bd->datagram_used == 0))
return;
360 if (bd->datagram_used == 0) bd->datagram_head = 0;
372void fr_tls_bio_dbuff_clear(fr_tls_bio_dbuff_t *bd)
377 bd->datagram_head = bd->datagram_used = 0;
383static int _fr_tls_bio_dbuff_free(fr_tls_bio_dbuff_t *bd)
394fr_dbuff_t *fr_tls_bio_dbuff_out(fr_tls_bio_dbuff_t *bd)
396 return &bd->dbuff_out;
402fr_dbuff_t *fr_tls_bio_dbuff_in(fr_tls_bio_dbuff_t *bd)
404 return &bd->dbuff_in;
422BIO *fr_tls_bio_dbuff_alloc(fr_tls_bio_dbuff_t **
out, TALLOC_CTX *bio_ctx, TALLOC_CTX *buff_ctx,
423 size_t init,
size_t max,
bool free_buff)
425 fr_tls_bio_dbuff_t *bd;
427 MEM(bd = talloc_zero(bio_ctx, fr_tls_bio_dbuff_t));
428 MEM(bd->bio = BIO_new(tls_bio_talloc_meth));
429 BIO_set_data(bd->bio, bd);
436 bd->dbuff_out.is_const = 1;
437 bd->free_buff = free_buff;
439 talloc_set_destructor(bd, _fr_tls_bio_dbuff_free);
452uint8_t *fr_tls_bio_dbuff_thread_local_finalise(
void)
454 return fr_tls_bio_dbuff_finalise(tls_bio_talloc_agg);
465char *fr_tls_bio_dbuff_thread_local_finalise_bstr(
void)
467 return fr_tls_bio_dbuff_finalise_bstr(tls_bio_talloc_agg);
474void fr_tls_bio_dbuff_thread_local_clear(
void)
476 fr_tls_bio_dbuff_t *bd = tls_bio_talloc_agg;
479 if (
unlikely(!bd->dbuff_in.buff))
return;
482 tls_bio_dbuff_detach(bd);
488static int _fr_tls_bio_dbuff_thread_local_free(
void *bio_talloc_agg)
490 fr_tls_bio_dbuff_t *our_bio_talloc_agg = talloc_get_type_abort(bio_talloc_agg, fr_tls_bio_dbuff_t);
503BIO *fr_tls_bio_dbuff_thread_local(TALLOC_CTX *ctx,
size_t init,
size_t max)
505 fr_tls_bio_dbuff_t *bd = tls_bio_talloc_agg;
508 fr_tls_bio_dbuff_alloc(&bd, NULL, ctx,
init,
max,
true);
514 fr_assert_msg(!tls_bio_talloc_agg->dbuff_out.buff,
"BIO not finalised");
518 return tls_bio_talloc_agg->bio;
527static long _tls_bio_talloc_ctrl_cb(BIO *bio,
int cmd,
UNUSED long num,
UNUSED void *ptr)
529 fr_tls_bio_dbuff_t *bd = talloc_get_type_abort(BIO_get_data(bio), fr_tls_bio_dbuff_t);
532 case BIO_CTRL_PENDING:
535 case BIO_CTRL_WPENDING:
542 fr_tls_bio_dbuff_reset(bd);
556int fr_tls_bio_init(
void)
568 tls_bio_talloc_meth = BIO_meth_new(BIO_get_new_index() | BIO_TYPE_SOURCE_SINK,
"fr_tls_bio_dbuff_t");
569 if (
unlikely(!tls_bio_talloc_meth))
return -1;
576 BIO_meth_set_write(tls_bio_talloc_meth, _tls_bio_talloc_write_cb);
577 BIO_meth_set_puts(tls_bio_talloc_meth, _tls_bio_talloc_puts_cb);
578 BIO_meth_set_read(tls_bio_talloc_meth, _tls_bio_talloc_read_cb);
579 BIO_meth_set_gets(tls_bio_talloc_meth, _tls_bio_talloc_gets_cb);
580 BIO_meth_set_ctrl(tls_bio_talloc_meth, _tls_bio_talloc_ctrl_cb);
588void fr_tls_bio_free(
void)
590 if (tls_bio_talloc_meth) {
591 BIO_meth_free(tls_bio_talloc_meth);
592 tls_bio_talloc_meth = NULL;
#define fr_atexit_thread_local(_name, _free, _uctx)
#define USES_APPLE_DEPRECATED_API
int fr_dbuff_trim_talloc(fr_dbuff_t *dbuff, size_t len)
Trim a talloced dbuff to the minimum length required to represent the contained string.
size_t fr_dbuff_shift(fr_dbuff_t *dbuff, size_t shift)
Shift the contents of the dbuff, returning the number of bytes we managed to shift.
#define fr_dbuff_used(_dbuff_or_marker)
Return the number of bytes remaining between the start of the dbuff or marker and the current positio...
static void fr_dbuff_free_talloc(fr_dbuff_t *dbuff)
Free the talloc buffer associated with a dbuff.
#define fr_dbuff_current(_dbuff_or_marker)
Return the 'current' position of a dbuff or marker.
#define fr_dbuff_set_to_start(_dbuff_or_marker)
Reset the 'current' position of the dbuff or marker to the 'start' of the buffer.
#define fr_dbuff_out_memcpy(_out, _dbuff_or_marker, _outlen)
Copy exactly _outlen bytes from the dbuff.
#define fr_dbuff_remaining(_dbuff_or_marker)
Return the number of bytes remaining between the dbuff or marker and the end of the buffer.
#define fr_dbuff_in_bytes(_dbuff_or_marker,...)
Copy a byte sequence into a dbuff or marker.
#define fr_dbuff_in_memcpy_partial(_out, _in, _inlen)
Copy at most _inlen bytes into the dbuff.
#define FR_DBUFF_BIND_END_ABS(_dbuff_or_marker)
Create a new dbuff pointing to the same underlying buffer.
static fr_dbuff_t * fr_dbuff_init_talloc(TALLOC_CTX *ctx, fr_dbuff_t *dbuff, fr_dbuff_uctx_talloc_t *tctx, size_t init, size_t max)
Initialise a special dbuff which automatically extends as additional data is written.
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
static char buff[sizeof("18446744073709551615")+3]
init
Enter the EAP-IDENTITY state.
static fr_sbuff_err_t char size_t fr_sbuff_t * in
static fr_sbuff_err_t char size_t fr_sbuff_t size_t max
static fr_sbuff_err_t char ** out
static fr_sbuff_err_t char size_t * len