The FreeRADIUS server $Id: a4e7f8c94e8038b7627bcf52356b7ed15955c1d7 $
Loading...
Searching...
No Matches
tls.c
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or (at
5 * your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: d9410ea8b9b3d7f49abdab425329d001bfb70c08 $
19 * @file lib/bio/tls.c
20 * @brief Binary IO abstractions for TLS and DTLS connections
21 *
22 * The TLS bio sits between the application and an fd bio, which carries the encrypted records. The TLS bio
23 * owns the whole life of the TLS connection:
24 *
25 * 1. `fr_bio_tls_alloc()` allocates the bio and the `fr_tls_connection_t` from the request, and sets
26 * `conn->request`. The request must already use an interpreter.
27 * 2. `fr_bio_tls_connect()` takes the connection through every state which comes before application data:
28 * the connect() of the fd bio, the TLS or DTLS handshake, and the policies which run before and after
29 * the handshake. During these states the TLS bio reads and writes the fd bio, and owns the events of
30 * the fd in the event list of the interpreter.
31 * 3. When the connection can carry application data, the TLS bio removes the events of the fd, and calls
32 * the `connected` callback. From then on the application reads and writes the TLS bio in the same way as
33 * any other bio. A read takes encrypted data from the fd bio, passes the encrypted data through
34 * OpenSSL, and returns the decrypted application data. A write encrypts the application data, and
35 * writes the encrypted records to the fd bio.
36 *
37 * The next bio MUST be a fd bio. If the connection fails at any point, the TLS bio removes the events of
38 * the fd, and calls the `failed` callback. The `failed` callback must not free the bio, as the failure can
39 * happen inside a read or a write on the bio.
40 *
41 * The bio and the `fr_tls_connection_t` are allocated from the request, so freeing the request frees both.
42 * Freeing the bio cancels the request, as the request has a frame which points to the connection.
43 *
44 * After each read or write to the fd bio, the TLS bio calls `fr_tls_connection_io_error()` to decide what to
45 * do next: try again, wait, or stop. `fr_tls_connection_io_error()` also tells the TLS connection about EOF
46 * and fatal errors.
47 *
48 * @copyright 2026 Network RADIUS SAS (legal@networkradius.com)
49 */
50
51#include <freeradius-devel/server/base.h>
52
53#include <freeradius-devel/tls/base.h>
54#include <freeradius-devel/tls/connection.h>
55
56#include <freeradius-devel/unlang/interpret.h>
57
58#include <freeradius-devel/bio/bio_priv.h>
59#include <freeradius-devel/bio/fd.h>
60#include <freeradius-devel/bio/tls.h>
61
62/** The TLS bio
63 *
64 */
67
68 fr_tls_connection_t *conn; //!< The TLS connection, which is a child of the bio.
69 ///< `conn->request` is the request which the bio came from.
70
71 fr_event_list_t *el; //!< The event list of the interpreter.
72 bool events; //!< The bio owns the events of the fd, which it has until the
73 ///< connection is connected. The event loop can remove the
74 ///< events by itself, e.g. at EOF, so the bio keeps no pointer.
75 int fd; //!< The fd of the next bio.
76
77 SSL_CTX *ssl_ctx; //!< Used to create the TLS session.
78 bool client; //!< Act as the client, and connect to a server.
79 bool client_cert; //!< For a server, require a client certificate.
80
81 bool write_wait; //!< The write event of the fd is active.
82
83 void *packet_ctx; //!< Passed to the next bio when writing encrypted records.
84 ///< Set only while `fr_bio_tls_write()` runs. Records which
85 ///< are written later, by `fr_bio_tls_write_resume()`, have
86 ///< no `packet_ctx`, as the caller's `packet_ctx` may be gone.
87
88 size_t clean_len; //!< How much decrypted data is in `clean_out`.
89 size_t clean_offset; //!< How much of the decrypted data the caller has read.
90
91 ssize_t next_error; //!< The error which the next bio returned from a write.
92
93 bool write_blocked; //!< The next bio is blocked. Encrypted records wait in the
94 ///< TLS connection until `fr_bio_tls_write_resume()` runs.
95
96 uint8_t buffer[SSL3_RT_MAX_PLAIN_LENGTH]; //!< Encrypted data read from the next bio.
97};
98
101 { 0 }
102};
103
106 { 0 }
107};
108
109/** Start or stop waiting for the fd to have room for more records
110 *
111 * The event of the fd is inserted with a write callback, and then the write event is suspended, as an fd
112 * which has room fires the write event on every pass of the event loop. The write event is active only
113 * while encrypted records are waiting for room.
114 *
115 * A suspend reads the active callback and a resume reads the suspended callback, so a suspend and a resume
116 * have to alternate. `write_wait` records whether the write event is active.
117 *
118 * @return
119 * - 0 on success, or when the bio does not own the events of the fd
120 * - <0 on error
121 */
122static int fr_bio_tls_write_wait(fr_bio_tls_t *my, bool wait)
123{
124 if (!my->events || (my->write_wait == wait)) return 0;
125
126 if (fr_event_filter_update(my->el, my->fd, FR_EVENT_FILTER_IO, wait ? resume_write : pause_write) < 0) {
127 fr_strerror_const_push("Failed updating the write event of the TLS connection");
128 return -1;
129 }
130
131 my->write_wait = wait;
132
133 return 0;
134}
135
136/** Stop owning the events of the fd
137 *
138 */
139static void fr_bio_tls_events_delete(fr_bio_tls_t *my)
140{
141 if (!my->events) return;
142
143 /*
144 * Fails harmlessly when the event loop has already removed the events.
145 */
146 (void) fr_event_fd_delete(my->el, my->fd, FR_EVENT_FILTER_IO);
147 my->events = false;
148 my->write_wait = false;
149}
150
151/** Tell the next bio that it can write again
152 *
153 * The next bio does not know that the event loop saw the fd become writable.
154 */
156{
157 fr_bio_common_t *this = (fr_bio_common_t *) next;
158
159 if (this->priv_cb.write_resume) (void) this->priv_cb.write_resume(next);
160}
161
162/** Stop the connection, and tell the application
163 *
164 * This function is for failures which the TLS connection does not know about, i.e. before the connection
165 * has started.
166 */
167static void fr_bio_tls_failed(fr_bio_tls_t *my, fr_tls_connection_fail_t reason, int error)
168{
170
171 my->conn->failed = reason;
172 my->conn->error = error;
173
174 my->bio.read = fr_bio_shutdown_read;
175 my->bio.write = fr_bio_shutdown_write;
176
177 if (my->cb.failed) my->cb.failed(&my->bio);
178}
179
180/** Write encrypted records to the next bio
181 *
182 * `fr_tls_connection_write()` calls this function once for each block of encrypted data in the TLS
183 * connection. For datagrams, each block is one datagram.
184 *
185 * A partial write means that the fd bio is out of room, so we assume that writes are blocked, in the same
186 * way as `fr_bio_mem_write_next()`. For every other result, `fr_tls_connection_io_error()` decides what
187 * to do.
188 *
189 * On EOF or a fatal error, `fr_tls_connection_io_error()` tells the TLS connection, which runs the
190 * `failed` callback of the application.
191 *
192 * @return
193 * - >0 the amount of data which was written
194 * - 0 writes are blocked. The data stays in the TLS connection, and `fr_bio_tls_write_resume()`
195 * writes the data.
196 * - <0 the write failed. The error is saved in `next_error`.
197 */
198static ssize_t fr_bio_tls_conn_write(fr_tls_connection_t *conn, uint8_t const *data, size_t size)
199{
200 fr_bio_tls_t *my = talloc_get_type_abort(conn->uctx, fr_bio_tls_t);
201 fr_bio_t *next;
202 ssize_t slen;
203
204 /*
205 * An earlier write was partial, or blocked. Leave the data in the TLS connection until
206 * `fr_bio_tls_write_resume()` runs.
207 */
208 if (my->write_blocked) return 0;
209
210 next = fr_bio_next(&my->bio);
211 fr_assert(next != NULL);
212
213retry:
214 slen = next->write(next, my->packet_ctx, data, size);
215 if (slen > 0) {
216 if ((size_t) slen == size) {
217 /*
218 * Something went out, so the fd had room. Stop waiting for room, which does
219 * nothing when the bio is not waiting.
220 */
221 if (fr_bio_tls_write_wait(my, false) < 0) return -1;
222 return slen;
223 }
224
225 /*
226 * Tell the previous bios that writes are blocked. The data has been written, so we
227 * return how much was written, even if a previous bio returns an error. Otherwise the
228 * TLS connection would write the same data again.
229 */
230 my->write_blocked = true;
231 (void) fr_bio_write_blocked(&my->bio);
232 if (fr_bio_tls_write_wait(my, true) < 0) return -1;
233 return slen;
234 }
235
236 /*
237 * The fd bio returns 0 after it shuts the chain down for an error such as `EPIPE`.
238 */
239 my->next_error = (slen < 0) ? slen : fr_bio_error(SHUTDOWN);
240
241 /*
242 * The fd bio calls its `write_blocked` callback before returning `IO_WOULD_BLOCK`, and the
243 * callback may change `errno`.
244 */
245 if (slen == fr_bio_error(IO_WOULD_BLOCK)) errno = EAGAIN;
246
247 switch (fr_tls_connection_io_error(conn, slen)) {
248 case FR_TLS_CONNECTION_IO_RETRY:
249 goto retry;
250
251 case FR_TLS_CONNECTION_IO_BLOCKED:
252 my->write_blocked = true;
253 if (fr_bio_tls_write_wait(my, true) < 0) return -1;
254 return 0;
255
256 /*
257 * `write()` failed, so the result cannot be "no error". Treat the impossible value as fatal.
258 */
259 case FR_TLS_CONNECTION_IO_OK:
260 case FR_TLS_CONNECTION_IO_EOF:
261 case FR_TLS_CONNECTION_IO_FATAL:
262 break;
263 }
264
265 return -1;
266}
267
268static ssize_t fr_bio_tls_read(fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size);
269static ssize_t fr_bio_tls_write(fr_bio_t *bio, void *packet_ctx, void const *buffer, size_t size);
270
271/** The TLS connection can carry application data
272 *
273 * The TLS connection calls this function once, when the connection enters the `TLS_CONNECTION_CONNECTED`
274 * state. The application owns the fd from now on, so the events of the fd go away before the application
275 * hears about the connection. The application can then read and write the bio.
276 */
277static void fr_bio_tls_conn_connected(fr_tls_connection_t *conn)
278{
279 fr_bio_tls_t *my = talloc_get_type_abort(conn->uctx, fr_bio_tls_t);
280
282
283 my->bio.read = fr_bio_tls_read;
284 my->bio.write = fr_bio_tls_write;
285
286 if (my->cb.connected) my->cb.connected(&my->bio);
287}
288
289/** The TLS connection failed
290 *
291 * The TLS connection runs the `close` callback only after a failure. After a failure the bio cannot read
292 * or write, and the application decides when to free the bio.
293 */
294static void fr_bio_tls_conn_close(fr_tls_connection_t *conn)
295{
296 fr_bio_tls_t *my = talloc_get_type_abort(conn->uctx, fr_bio_tls_t);
297
299
300 my->bio.read = fr_bio_shutdown_read;
301 my->bio.write = fr_bio_shutdown_write;
302
303 if (my->cb.failed) my->cb.failed(&my->bio);
304}
305
306/** Write any pending encrypted records to the next bio
307 *
308 * @return
309 * - 1 nothing is left to write
310 * - 0 the next bio is blocked, and some data is still waiting
311 * - <0 the error which the next bio returned
312 */
313static int fr_bio_tls_flush(fr_bio_tls_t *my)
314{
315 fr_tls_session_t *tls_session = my->conn->tls_session;
316
317 if (fr_tls_connection_write(my->conn) < 0) return (int) my->next_error;
318
319 if (fr_dbuff_remaining(tls_session->dirty_out) > 0) return 0;
320
321 return 1;
322}
323
324/** Record that the next bio is blocked
325 *
326 */
328{
329 fr_bio_tls_t *my = talloc_get_type_abort(bio, fr_bio_tls_t);
330
331 /*
332 * If we're blocked, then either we're waiting for connect() to finish, or there's pending
333 * application data.
334 */
335 fr_assert((my->conn->state != TLS_CONNECTION_CONNECTED) ||
336 (fr_dbuff_remaining(my->conn->tls_session->dirty_out) > 0));
337
338 my->write_blocked = true;
339
340 return 1;
341}
342
343/** Write the encrypted records which were waiting for the next bio
344 *
345 * @return
346 * - 1 writes can resume
347 * - 0 still blocked
348 * - <0 on error
349 */
351{
352 fr_bio_tls_t *my = talloc_get_type_abort(bio, fr_bio_tls_t);
353 int rcode;
354
355 /*
356 * `fr_bio_tls_conn_write()` sets `write_blocked` again if the next bio is still blocked.
357 */
358 my->write_blocked = false;
359
360 rcode = fr_bio_tls_flush(my);
361 if (rcode <= 0) return rcode;
362
363 if (!my->cb.write_resume) return 1;
364
365 return my->cb.write_resume(bio);
366}
367
368/** Encrypt application data, and write the encrypted records to the next bio
369 *
370 * `SSL_MODE_ENABLE_PARTIAL_WRITE` is not set, so OpenSSL encrypts all of the data passed to
371 * `SSL_write()`. The application data therefore counts as written as soon as OpenSSL encrypts the data.
372 * If the next bio blocks, the encrypted records wait in the TLS connection, and the next write or
373 * `fr_bio_tls_write_resume()` writes the records later. Until the waiting records reach the next bio,
374 * the bio returns `fr_bio_error(IO_WOULD_BLOCK)` for new application data. The amount of waiting data
375 * therefore cannot grow without limit.
376 *
377 * @return
378 * - >0 the amount of application data which was written
379 * - `fr_bio_error(IO_WOULD_BLOCK)` when encrypted records are still waiting for the next bio
380 * - <0 on error
381 */
382static ssize_t fr_bio_tls_write_data(fr_bio_tls_t *my, void const *buffer, size_t size)
383{
384 fr_tls_session_t *tls_session = my->conn->tls_session;
385 uint8_t const *p = buffer;
386 size_t written = 0;
387 int rcode;
388
389 /*
390 * Writes are blocked. `fr_bio_tls_write_resume()` writes the waiting records.
391 *
392 * A blocked bio always has encrypted records which have not reached the next bio.
393 */
394 if (my->write_blocked) {
395 fr_assert(fr_dbuff_remaining(tls_session->dirty_out) > 0);
396 return fr_bio_error(IO_WOULD_BLOCK);
397 }
398
399 /*
400 * A read can leave encrypted records waiting. `fr_bio_tls_flush()` writes the waiting
401 * records first, so that the next bio receives the records in order.
402 */
403 if (fr_dbuff_remaining(tls_session->dirty_out) > 0) {
404 rcode = fr_bio_tls_flush(my);
405 if (rcode < 0) return rcode;
406 if (rcode == 0) return fr_bio_error(IO_WOULD_BLOCK);
407 }
408
409 while (written < size) {
410 size_t chunk = size - written;
411
412 if (chunk > fr_dbuff_remaining(&tls_session->clean_in)) chunk = fr_dbuff_remaining(&tls_session->clean_in);
413
414 (void) fr_dbuff_in_memcpy(&tls_session->clean_in, p + written, chunk);
415
416 /*
417 * After a failure inside OpenSSL, the TLS connection cannot continue. The TLS bio is the
418 * bio which failed, so the TLS bio shuts the chain down.
419 */
420 if (fr_tls_session_send(my->conn->request, tls_session) < 0) {
421 fr_strerror_const("Failed encrypting TLS application data");
422 (void) fr_bio_shutdown(&my->bio);
423 return fr_bio_error(GENERIC);
424 }
425
426 /*
427 * OpenSSL has taken the data, so the data has been written, even if the encrypted
428 * records have not yet reached the next bio.
429 */
430 written += chunk;
431
432 rcode = fr_bio_tls_flush(my);
433 if (rcode == 1) continue;
434
435 /*
436 * Writes are blocked, or the write failed. OpenSSL has already taken the application
437 * data, so we return how much data OpenSSL took, and not the error. If the caller wrote
438 * the same data again, the peer would get the data twice.
439 */
440 break;
441 }
442
443 return written;
444}
445
446static ssize_t fr_bio_tls_write(fr_bio_t *bio, void *packet_ctx, void const *buffer, size_t size)
447{
448 fr_bio_tls_t *my = talloc_get_type_abort(bio, fr_bio_tls_t);
449 ssize_t rcode;
450
451 /*
452 * If we're not writing actual data, then flush the buffer.
453 *
454 * A blocked TLS BIO is either waiting on connect(), or it has waiting records. We clear the
455 * blocked flag so that the write() tries the next BIO. The write function will take care of
456 * either writing all of the data, or setting the write_blocked flag again.
457 */
458 if (!buffer) {
459 my->write_blocked = false;
460
461 rcode = fr_bio_tls_flush(my);
462 if (rcode < 0) {
463 fr_assert((rcode != fr_bio_error(IO_WOULD_BLOCK)) || my->write_blocked);
464 return rcode;
465 }
466 if (rcode > 0) {
467 fr_assert(!my->write_blocked);
468 return 0;
469 }
470
471 fr_assert(my->write_blocked);
472 return fr_bio_error(IO_WOULD_BLOCK);
473 }
474
475 my->packet_ctx = packet_ctx;
476 rcode = fr_bio_tls_write_data(my, buffer, size);
477 my->packet_ctx = NULL;
478
479 return rcode;
480}
481
482/** Check whether OpenSSL holds data which the bio has not yet processed
483 *
484 */
485static bool fr_bio_tls_pending(fr_bio_tls_t *my)
486{
487 fr_tls_session_t *tls_session = my->conn->tls_session;
488
489 return (fr_dbuff_remaining(fr_tls_bio_dbuff_out(tls_session->into_ssl)) > 0) ||
490 (SSL_pending(tls_session->ssl) > 0);
491}
492
493/** Decrypt one record which is waiting in OpenSSL
494 *
495 * @return
496 * - 1 one record was processed. The record may not contain application data.
497 * - 0 OpenSSL needs more data for a complete record
498 * - <0 on error
499 */
500static int fr_bio_tls_decrypt(fr_bio_tls_t *my)
501{
502 fr_tls_session_t *tls_session = my->conn->tls_session;
503 int rcode;
504
505 rcode = fr_tls_session_recv(my->conn->request, tls_session);
506 if (rcode < 0) {
507 /*
508 * After a failure inside OpenSSL, the TLS connection cannot continue. The TLS bio is the
509 * bio which failed, so the TLS bio shuts the chain down.
510 */
511 fr_strerror_const("Failed decrypting TLS application data");
512 (void) fr_bio_shutdown(&my->bio);
513 return fr_bio_error(GENERIC);
514 }
515
516 if (rcode == 1) return 0;
517
518 my->clean_len = fr_dbuff_used(&tls_session->clean_out);
519 my->clean_offset = 0;
520
521 /*
522 * `fr_tls_session_recv()` can leave encrypted records in `dirty_out`. When writes are
523 * blocked, `fr_bio_tls_write_resume()` writes the records later.
524 */
525 if (fr_dbuff_remaining(tls_session->dirty_out) > 0) {
526 rcode = fr_bio_tls_flush(my);
527 if (rcode < 0) return rcode;
528 }
529
530 return 1;
531}
532
533/** Copy decrypted data which the caller has not yet read into the caller's buffer
534 *
535 */
536static size_t fr_bio_tls_clean_read(fr_bio_tls_t *my, void *buffer, size_t size)
537{
538 size_t used = my->clean_len - my->clean_offset;
539
540 if (size > used) size = used;
541
542 memcpy(buffer, fr_dbuff_start(&my->conn->tls_session->clean_out) + my->clean_offset, size);
543 my->clean_offset += size;
544
545 return size;
546}
547
548/** Read encrypted data from the next bio, and return the decrypted application data
549 *
550 * One record can hold more application data than the caller asked for. The rest of the data stays in
551 * the TLS connection, and the next read returns the rest. The bio asks OpenSSL to decrypt the next
552 * record only after the caller has read all of the data from the previous record.
553 *
554 * @return
555 * - >0 the amount of application data which was read
556 * - 0 no application data is available, or the peer closed the TLS connection
557 * - <0 on error
558 */
559static ssize_t fr_bio_tls_read(fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size)
560{
561 fr_bio_tls_t *my = talloc_get_type_abort(bio, fr_bio_tls_t);
562 fr_tls_connection_t *conn = my->conn;
563 fr_tls_session_t *tls_session = conn->tls_session;
564 fr_bio_t *next;
565
566 next = fr_bio_next(&my->bio);
567 fr_assert(next != NULL);
568
569 while (true) {
570 size_t room;
571 ssize_t rcode;
572
573 if (my->clean_offset < my->clean_len) return fr_bio_tls_clean_read(my, buffer, size);
574
575 /*
576 * Decrypt the records which OpenSSL already has. A record which holds no application
577 * data, such as a session ticket, produces no data, and the loop then decrypts the next
578 * record.
579 */
580 if (fr_bio_tls_pending(my)) {
581 rcode = fr_bio_tls_decrypt(my);
582 if (rcode < 0) return rcode;
583
584 if (rcode == 1) {
585 if (my->clean_len > 0) continue;
586
587 /*
588 * The peer sent a TLS `close_notify` alert, which ends the TLS connection.
589 * No more application data will arrive.
590 */
591 if ((SSL_get_shutdown(tls_session->ssl) & SSL_RECEIVED_SHUTDOWN) != 0) {
592 fr_bio_eof(&my->bio);
593 return 0;
594 }
595
596 if (fr_bio_tls_pending(my)) continue;
597 }
598 }
599
600 /*
601 * OpenSSL needs more data. When `dirty_in` is full, and OpenSSL still needs more data,
602 * the peer sent a record which is too large.
603 */
604 room = fr_dbuff_extend_lowat(NULL, tls_session->dirty_in, sizeof(my->buffer));
605 if (room == 0) {
606 fr_strerror_const("TLS record is too large");
607 (void) fr_bio_shutdown(&my->bio);
608 return fr_bio_error(BUFFER_FULL);
609 }
610 if (room > sizeof(my->buffer)) room = sizeof(my->buffer);
611
612 rcode = next->read(next, packet_ctx, my->buffer, room);
613 if (rcode <= 0) {
614 /*
615 * The fd bio has already shut the chain down for EOF, and for fatal errors. That
616 * shutdown may have run `fr_bio_tls_shutdown()`. On EOF or a fatal error,
617 * `fr_tls_connection_io_error()` tells the TLS connection, which runs the `failed`
618 * callback.
619 *
620 * The fd bio calls its `read_blocked` callback before returning `IO_WOULD_BLOCK`,
621 * and the callback may change `errno`.
622 */
623 if (rcode == fr_bio_error(IO_WOULD_BLOCK)) errno = EAGAIN;
624
625 switch (fr_tls_connection_io_error(conn, rcode)) {
626 case FR_TLS_CONNECTION_IO_RETRY:
627 continue;
628
629 /*
630 * Blocked, or a datagram socket with no data. Wait for the next read event.
631 */
632 case FR_TLS_CONNECTION_IO_BLOCKED:
633 case FR_TLS_CONNECTION_IO_OK:
634 case FR_TLS_CONNECTION_IO_EOF:
635 case FR_TLS_CONNECTION_IO_FATAL:
636 break;
637 }
638
639 return rcode;
640 }
641
642 /*
643 * `room` limits the read to the free space in `dirty_in`, so the copy cannot be
644 * partial.
645 */
646 (void) fr_dbuff_in_memcpy(tls_session->dirty_in, my->buffer, (size_t) rcode);
647 }
648}
649
650/** Return the decrypted data which remains after the next bio reached EOF, and then return EOF
651 *
652 */
653static ssize_t fr_bio_tls_read_eof(fr_bio_t *bio, UNUSED void *packet_ctx, void *buffer, size_t size)
654{
655 fr_bio_tls_t *my = talloc_get_type_abort(bio, fr_bio_tls_t);
656 int rcode;
657
658 while (true) {
659 if (my->clean_offset < my->clean_len) return fr_bio_tls_clean_read(my, buffer, size);
660
661 if (!fr_bio_tls_pending(my)) break;
662
663 /*
664 * The next bio is at EOF, so an incomplete record never completes.
665 */
666 rcode = fr_bio_tls_decrypt(my);
667 if (rcode < 0) return rcode;
668 if (rcode == 0) break;
669 }
670
671 /*
672 * Clear `priv_cb.eof`, so that `fr_bio_eof()` does not call `fr_bio_tls_eof()` again.
673 * `fr_bio_eof()` then tells the previous bios that the TLS bio is at EOF.
674 */
675 my->priv_cb.eof = NULL;
676 fr_bio_eof(&my->bio);
677 return 0;
678}
679
680/** Handle EOF from the next bio
681 *
682 * When the TLS bio still holds data for the application, this function sets the read function to
683 * `fr_bio_tls_read_eof()`. `fr_bio_tls_read_eof()` returns the remaining data, and then signals EOF.
684 *
685 * @return
686 * - 1 the TLS bio holds no data for the application, so `fr_bio_eof()` continues to the previous bios
687 * - 0 the TLS bio still holds data for the application
688 */
689static int fr_bio_tls_eof(fr_bio_t *bio)
690{
691 fr_bio_tls_t *my = talloc_get_type_abort(bio, fr_bio_tls_t);
692
693 /*
694 * Before the connection is connected, there is no application data.
695 */
696 if (my->conn->state != TLS_CONNECTION_CONNECTED) return 1;
697
698 if ((my->clean_offset == my->clean_len) && !fr_bio_tls_pending(my)) return 1;
699
700 my->bio.read = fr_bio_tls_read_eof;
701
702 return 0;
703}
704
705
706/** Disconnect the bio from the fd
707 *
708 * This function runs when a shutdown of the chain completes, and when the bio is freed. The events of the
709 * fd go away, and the application can no longer read or write. The TLS connection is a child of the bio, so
710 * the TLS connection stays valid until the bio is freed.
711 */
713{
714 fr_bio_tls_t *my = talloc_get_type_abort(bio, fr_bio_tls_t);
715
717
718 my->bio.read = fr_bio_shutdown_read;
719 my->bio.write = fr_bio_shutdown_write;
720
721 return 0;
722}
723
724/** Application data cannot move until the connection is connected
725 *
726 * A read or write before the `connected` callback runs gets "would block". The write is a flush request from
727 * the fd bio, which has nothing to flush.
728 */
730{
731 return fr_bio_error(IO_WOULD_BLOCK);
732}
733
735{
736 if (size == SIZE_MAX) return 0;
737
738 return fr_bio_error(IO_WOULD_BLOCK);
739}
740
741/** A record arrived on the fd, so hand the record to the TLS connection
742 *
743 * Reading the fd is all this function does. Everything the record means to TLS is `fr_tls_connection_recv()`'s
744 * business.
745 */
746static void fr_bio_tls_el_read(UNUSED fr_event_list_t *el, UNUSED int fd, UNUSED int flags, void *uctx)
747{
748 fr_bio_tls_t *my = talloc_get_type_abort(uctx, fr_bio_tls_t);
749 fr_bio_t *next = fr_bio_next(&my->bio);
750 ssize_t slen;
751
752 while (true) {
753 slen = next->read(next, NULL, my->buffer, sizeof(my->buffer));
754 if (slen > 0) {
755 fr_tls_connection_recv(my->conn, my->buffer, (size_t) slen);
756 return;
757 }
758
759 /*
760 * The fd bio calls its `read_blocked` callback before returning `IO_WOULD_BLOCK`, and the
761 * callback may change `errno`.
762 */
763 if (slen == fr_bio_error(IO_WOULD_BLOCK)) errno = EAGAIN;
764
765 /*
766 * The connection records what happened, and ends itself when the result ends it. An
767 * interrupted read is run again. A blocked read waits for the next read event, as an fd
768 * which still holds a record fires the read event again.
769 */
770 if (fr_tls_connection_io_error(my->conn, slen) != FR_TLS_CONNECTION_IO_RETRY) return;
771 }
772}
773
774/** The fd is ready for writes
775 *
776 * Run the connection state machine, which either flushes pending data, or keeps going with the next TLS
777 * state. The event loop calls this function only after a write blocked, see `fr_bio_tls_write_wait()`.
778 *
779 * `fr_tls_connection_process()` writes the rest of the encrypted records, and then checks the connection
780 * again. The check ends a connection whose handshake finished while a record was still waiting.
781 */
782static void fr_bio_tls_el_write(UNUSED fr_event_list_t *el, UNUSED int fd, UNUSED int flags, void *uctx)
783{
784 fr_bio_tls_t *my = talloc_get_type_abort(uctx, fr_bio_tls_t);
785
786 /*
787 * Stop the event first, as an fd which has room fires the event on every pass of the event
788 * loop. Writing the records which are waiting starts the event again if the fd is still full.
789 */
790 if (fr_bio_tls_write_wait(my, false) < 0) {
791 fr_bio_tls_failed(my, TLS_CONNECTION_FAIL_APPLICATION, 0);
792 return;
793 }
794
795 my->write_blocked = false;
797
798 fr_tls_connection_process(my->conn);
799}
800
801/** The fd failed
802 *
803 */
804static void fr_bio_tls_el_error(UNUSED fr_event_list_t *el, UNUSED int fd, UNUSED int flags, int fd_errno, void *uctx)
805{
806 fr_bio_tls_t *my = talloc_get_type_abort(uctx, fr_bio_tls_t);
807
808 if (fd_errno == 0) {
809 (void) fr_tls_connection_io_error(my->conn, 0);
810 return;
811 }
812
813 /*
814 * The event loop reports the error rather than leaving it in `errno`, so put it back where
815 * `fr_tls_connection_io_error()` reads it.
816 */
817 errno = fd_errno;
818 (void) fr_tls_connection_io_error(my->conn, -1);
819}
820
821/** The fd is connected, so start the TLS connection
822 *
823 * Create the TLS session, put the events of the fd in the event list, and start the connection state
824 * machine. The state machine runs in one frame of the request, which `fr_tls_connection_push()` pushes.
825 * The TLS bio does the IO for the state machine.
826 *
827 * @return
828 * - 0 on success
829 * - <0 on error
830 */
831static int fr_bio_tls_handshake_start(fr_bio_tls_t *my)
832{
833 fr_tls_connection_t *conn = my->conn;
834 request_t *request = conn->request;
835 fr_bio_t *next = fr_bio_next(&my->bio);
836 fr_bio_fd_info_t const *info = fr_bio_fd_info(next);
837
838 my->fd = info->socket.fd;
839
840 /*
841 * The application knows more about what identifies a connection, so it can set the name before it
842 * calls fr_bio_tls_connect().
843 */
844 if (!conn->name) {
845 conn->name = talloc_asprintf(conn, "%s %s", (info->socket.type == SOCK_DGRAM) ? "DTLS" : "TLS",
846 info->name ? info->name : "");
847 if (!conn->name) return -1;
848 }
849
850 if (conn->client) {
851 conn->tls_session = fr_tls_session_alloc_client(request, my->ssl_ctx, request);
852 } else {
853 conn->tls_session = fr_tls_session_alloc_server(request, my->ssl_ctx, request, my->client_cert);
854 }
855 if (!conn->tls_session) return -1;
856
857 /*
858 * Bind the DTLS cookie to the socket which the connection runs on. The library hashes the whole
859 * structure with a key of its own, and never reads it.
860 */
861 if (info->socket.type == SOCK_DGRAM) conn->tls_session->cookie = &info->socket;
862
863 /*
864 * The events exist before the connection starts, so that a write which blocks during the first
865 * round can ask for the write event. A fd which has room fires the write event on every pass of
866 * the event loop, so suspend the write event until it is needed.
867 */
868 if (fr_event_fd_insert(my, NULL, my->el, my->fd,
870 fr_strerror_const_push("Failed adding the TLS connection to the event loop");
871 return -1;
872 }
873 my->events = true;
874
875 my->write_wait = true;
876 if (fr_bio_tls_write_wait(my, false) < 0) {
878 return -1;
879 }
880
881 if (fr_tls_connection_push(conn) < 0) {
883 fr_strerror_const_push("Failed starting the TLS connection");
884 return -1;
885 }
886
887 /*
888 * Run the interpreter once, so that the first frame yields. `unlang_interpret_mark_runnable()`
889 * acts only on a frame which has yielded.
890 */
892
893 /*
894 * Run `new session { ... }` and, for a client, `load session`. A server then waits for the
895 * ClientHello. A client has to send the ClientHello.
896 */
897 fr_tls_connection_wake(conn);
898
899 return 0;
900}
901
902/** Find the TLS bio from the fd bio
903 *
904 * The TLS bio is always the bio before the fd bio.
905 */
906static fr_bio_tls_t *fr_bio_tls_from_fd(fr_bio_t *fd_bio)
907{
908 fr_bio_t *prev = fr_bio_prev(fd_bio);
909
910 if (!prev) return NULL;
911
912 return talloc_get_type_abort(prev, fr_bio_tls_t);
913}
914
915/** The fd is connected
916 *
917 */
919{
920 fr_bio_tls_t *my = fr_bio_tls_from_fd(fd_bio);
921
922 if (!my) return;
923
924 if (fr_bio_tls_handshake_start(my) < 0) fr_bio_tls_failed(my, TLS_CONNECTION_FAIL_APPLICATION, 0);
925}
926
927/** The fd failed to connect
928 *
929 * The fd bio has recorded the error, and shuts down.
930 */
931static void fr_bio_tls_fd_error(fr_bio_t *fd_bio)
932{
933 fr_bio_tls_t *my = fr_bio_tls_from_fd(fd_bio);
934
935 if (!my) return;
936
937 fr_bio_tls_failed(my, TLS_CONNECTION_FAIL_SYSCALL, fr_bio_fd_info(fd_bio)->connect_errno);
938}
939
940/** Send a TLS `close_notify` alert to the peer
941 *
942 * RFC 9846 Section 6.1 requires that a party sends a `close_notify` alert before closing its write side
943 * of the connection. A TCP connection can be closed without writing, but a TLS connection cannot.
944 *
945 * The write is best effort. If the next bio is blocked, the alert stays in the TLS connection buffer, and
946 * the fd is closed anyway.
947 *
948 * The alert is not sent when the TLS connection is not connected, when the TLS connection failed, when
949 * the bio chain already shut down, or when the fd is at EOF or is not open.
950 *
951 * An application which frees the fd bio before the TLS bio MUST call this function first. Freeing the
952 * fd bio shuts down the whole chain, which stops writes in the TLS bio, so the TLS bio destructor can no
953 * longer send the alert.
954 *
955 * @param[in] my the TLS bio.
956 */
957void fr_bio_tls_close_send(fr_bio_tls_t *my)
958{
959 fr_bio_t *next = fr_bio_next(&my->bio);
960 fr_bio_fd_info_t const *info;
961
962 if (my->conn->state != TLS_CONNECTION_CONNECTED) return;
963 if (my->conn->failed != TLS_CONNECTION_FAIL_NONE) return;
964 if (my->bio.write == fr_bio_shutdown_write) return;
965
966 info = fr_bio_fd_info(next);
967 if (info->eof || (info->state != FR_BIO_FD_STATE_OPEN)) return;
968
969 fr_tls_session_close_send(my->conn->request, my->conn->tls_session);
970
971 /*
972 * Nothing can write to the bio after the alert. Setting the write function also stops a
973 * blocked write from running the `write_blocked` callbacks while the bio closes.
974 */
975 my->bio.write = fr_bio_shutdown_write;
976
977 (void) fr_bio_tls_flush(my);
978}
979
980/** Send any close_notify, stop the fd events, cancel the request, and then run the common bio destructor
981 *
982 * The application is freeing the bio, so the application does not care if there is a failed write when
983 * sending the `close_notify`. Delete the FD events before any writes.
984 *
985 * A failed write in the FD BIO causes it to close the FD.
986 *
987 * The request has a frame which points at the TLS connection, and the TLS connection is freed with the bio.
988 * Cancelling the request unwinds the frames nad frees the connection. The interpreter can then free the
989 * request.
990 */
991static int fr_bio_tls_destructor(fr_bio_tls_t *my)
992{
993 my->cb.failed = NULL;
994
995 (void) fr_event_fd_delete(my->el, my->fd, FR_EVENT_FILTER_IO);
996 my->events = false;
997 my->write_wait = false;
998
1000
1001 unlang_interpret_signal(my->conn->request, FR_SIGNAL_CANCEL);
1002
1003 return fr_bio_destructor((fr_bio_t *) my);
1004}
1005
1006/** Allocate a TLS bio
1007 *
1008 * The bio and the TLS connection are allocated from the request, so they cannot outlive the request. The
1009 * request must already use an interpreter, as the connection state machine runs in a frame of the request,
1010 * and the bio takes the event list from the interpreter. After allocating the bio, call `fr_bio_tls_connect()`.
1011 *
1012 * Use `fr_bio_cb_set()` to set the callbacks:
1013 *
1014 * - `connected` is called when the connection can carry application data. The fd events are gone, and the
1015 * application can read and write the bio.
1016 * - `failed` is called when the connection fails, for any reason, at any time. The reason is in
1017 * `conn->failed`, and `conn->error` holds the errno for system call failures. The callback must not free
1018 * the bio, as the callback can run from inside a read or a write on the bio. The callback can instead
1019 * arrange for the application to free the bio later, for example from the event loop.
1020 *
1021 * @param[in] request to allocate the bio and the connection from, and which runs the connection.
1022 * @param[in] next the fd bio which carries the encrypted records.
1023 * @param[in] ssl_ctx to create the TLS session from.
1024 * @param[in] client true to connect to a server, false to accept a connection.
1025 * @param[in] client_cert for a server, whether to require a client certificate. Ignored for a client.
1026 * @return
1027 * - the TLS bio
1028 * - `NULL` when the next bio is not an fd bio, when the request has no event list, or when an allocation
1029 * fails
1030 */
1031fr_bio_tls_t *fr_bio_tls_alloc(request_t *request, fr_bio_t *next, SSL_CTX *ssl_ctx, bool client, bool client_cert)
1032{
1033 fr_bio_tls_t *my;
1035
1036 if (!el) {
1037 fr_strerror_const("The request does not have an event list");
1038 return NULL;
1039 }
1040
1041 if (!talloc_check_name(next, "fr_bio_fd_t")) {
1042 fr_strerror_const("The next bio must be an fd bio");
1043 return NULL;
1044 }
1045
1046 my = talloc_zero(request, fr_bio_tls_t);
1047 if (!my) return NULL;
1048
1049 my->el = el;
1050 my->ssl_ctx = ssl_ctx;
1051 my->client = client;
1052 my->client_cert = client_cert;
1053 my->fd = fr_bio_fd_info(next)->socket.fd;
1054
1055 my->conn = fr_tls_connection_alloc(my, el->tl, fr_bio_tls_conn_write,
1057 if (!my->conn) {
1058 talloc_free(my);
1059 return NULL;
1060 }
1061 my->conn->uctx = my;
1062 my->conn->client = client;
1063 my->conn->request = request;
1064
1065 my->bio.read = fr_bio_tls_read_wait;
1066 my->bio.write = fr_bio_tls_write_wait_connected;
1067
1068 my->priv_cb.eof = fr_bio_tls_eof;
1069 my->priv_cb.shutdown = fr_bio_tls_shutdown;
1070 my->priv_cb.write_blocked = fr_bio_tls_write_blocked;
1071 my->priv_cb.write_resume = fr_bio_tls_write_resume;
1072
1073 fr_bio_chain(&my->bio, next);
1074
1075 talloc_set_destructor(my, fr_bio_tls_destructor);
1076 return my;
1077}
1078
1079/** The TLS connection, so the caller can set `conn->name`
1080 *
1081 */
1082fr_tls_connection_t *fr_bio_tls_conn(fr_bio_tls_t *my)
1083{
1084 return my->conn;
1085}
1086
1087/** Take the connection through every state which comes before application data
1088 *
1089 * The connection connects the fd bio, runs the TLS handshake, and runs
1090 * the policies which go with the handshake. A stream socket can take some time to connect, and the TLS bio
1091 * waits for the connect in the event list. A datagram socket, or a socket which the caller accepted, is
1092 * already connected, so the handshake starts before this function returns.
1093 *
1094 * The caller must wait for the `connected` or `failed` callback. A callback can run before this function
1095 * returns.
1096 *
1097 * @param[in] my the TLS bio.
1098 * @return
1099 * - 0 the connection has started.
1100 * - <0 the fd bio failed to connect. The `failed` callback has already run.
1101 */
1102int fr_bio_tls_connect(fr_bio_tls_t *my)
1103{
1104 if (fr_bio_fd_connect_full(fr_bio_next(&my->bio), my->el,
1105 fr_bio_tls_fd_connected, fr_bio_tls_fd_error, NULL, NULL) < 0) {
1106 return -1;
1107 }
1108
1109 return 0;
1110}
static int const char char buffer[256]
Definition acutest.h:641
fr_bio_write_t _CONST write
write to the underlying bio
Definition base.h:117
static fr_bio_t * fr_bio_prev(fr_bio_t *bio)
Definition base.h:122
fr_bio_read_t _CONST read
read from the underlying bio
Definition base.h:116
static fr_bio_t * fr_bio_next(fr_bio_t *bio)
Definition base.h:131
#define fr_bio_error(_x)
Definition base.h:200
static void fr_bio_tls_events_delete(fr_bio_tls_t *my)
Stop owning the events of the fd.
Definition tls.c:139
void fr_bio_tls_close_send(fr_bio_tls_t *my)
Send a TLS close_notify alert to the peer.
Definition tls.c:957
static void fr_bio_tls_el_write(UNUSED fr_event_list_t *el, UNUSED int fd, UNUSED int flags, void *uctx)
The fd is ready for writes.
Definition tls.c:782
static void fr_bio_tls_conn_connected(fr_tls_connection_t *conn)
The TLS connection can carry application data.
Definition tls.c:277
size_t clean_offset
How much of the decrypted data the caller has read.
Definition tls.c:89
static ssize_t fr_bio_tls_read(fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size)
Read encrypted data from the next bio, and return the decrypted application data.
Definition tls.c:559
static void fr_bio_tls_conn_close(fr_tls_connection_t *conn)
The TLS connection failed.
Definition tls.c:294
static ssize_t fr_bio_tls_read_wait(UNUSED fr_bio_t *bio, UNUSED void *packet_ctx, UNUSED void *buffer, UNUSED size_t size)
Application data cannot move until the connection is connected.
Definition tls.c:729
bool client
Act as the client, and connect to a server.
Definition tls.c:78
fr_tls_connection_t * fr_bio_tls_conn(fr_bio_tls_t *my)
The TLS connection, so the caller can set conn->name
Definition tls.c:1082
void * packet_ctx
Passed to the next bio when writing encrypted records.
Definition tls.c:83
bool events
The bio owns the events of the fd, which it has until the connection is connected.
Definition tls.c:72
static int fr_bio_tls_write_blocked(fr_bio_t *bio)
Record that the next bio is blocked.
Definition tls.c:327
static int fr_bio_tls_write_wait(fr_bio_tls_t *my, bool wait)
Start or stop waiting for the fd to have room for more records.
Definition tls.c:122
static ssize_t fr_bio_tls_write_data(fr_bio_tls_t *my, void const *buffer, size_t size)
Encrypt application data, and write the encrypted records to the next bio.
Definition tls.c:382
size_t clean_len
How much decrypted data is in clean_out.
Definition tls.c:88
static bool fr_bio_tls_pending(fr_bio_tls_t *my)
Check whether OpenSSL holds data which the bio has not yet processed.
Definition tls.c:485
static int fr_bio_tls_decrypt(fr_bio_tls_t *my)
Decrypt one record which is waiting in OpenSSL.
Definition tls.c:500
static void fr_bio_tls_fd_connected(fr_bio_t *fd_bio)
The fd is connected.
Definition tls.c:918
static fr_event_update_t const resume_write[]
Definition tls.c:104
FR_BIO_COMMON
Definition tls.c:66
ssize_t next_error
The error which the next bio returned from a write.
Definition tls.c:91
bool write_wait
The write event of the fd is active.
Definition tls.c:81
static ssize_t fr_bio_tls_write_wait_connected(UNUSED fr_bio_t *bio, UNUSED void *packet_ctx, UNUSED void const *buffer, size_t size)
Definition tls.c:734
int fd
The fd of the next bio.
Definition tls.c:75
static void fr_bio_tls_failed(fr_bio_tls_t *my, fr_tls_connection_fail_t reason, int error)
Stop the connection, and tell the application.
Definition tls.c:167
static void fr_bio_tls_fd_error(fr_bio_t *fd_bio)
The fd failed to connect.
Definition tls.c:931
SSL_CTX * ssl_ctx
Used to create the TLS session.
Definition tls.c:77
static void fr_bio_tls_el_error(UNUSED fr_event_list_t *el, UNUSED int fd, UNUSED int flags, int fd_errno, void *uctx)
The fd failed.
Definition tls.c:804
static int fr_bio_tls_write_resume(fr_bio_t *bio)
Write the encrypted records which were waiting for the next bio.
Definition tls.c:350
bool write_blocked
The next bio is blocked.
Definition tls.c:93
static ssize_t fr_bio_tls_read_eof(fr_bio_t *bio, UNUSED void *packet_ctx, void *buffer, size_t size)
Return the decrypted data which remains after the next bio reached EOF, and then return EOF.
Definition tls.c:653
static int fr_bio_tls_eof(fr_bio_t *bio)
Handle EOF from the next bio.
Definition tls.c:689
int fr_bio_tls_connect(fr_bio_tls_t *my)
Take the connection through every state which comes before application data.
Definition tls.c:1102
static void fr_bio_tls_el_read(UNUSED fr_event_list_t *el, UNUSED int fd, UNUSED int flags, void *uctx)
A record arrived on the fd, so hand the record to the TLS connection.
Definition tls.c:746
fr_bio_tls_t * fr_bio_tls_alloc(request_t *request, fr_bio_t *next, SSL_CTX *ssl_ctx, bool client, bool client_cert)
Allocate a TLS bio.
Definition tls.c:1031
bool client_cert
For a server, require a client certificate.
Definition tls.c:79
static int fr_bio_tls_flush(fr_bio_tls_t *my)
Write any pending encrypted records to the next bio.
Definition tls.c:313
uint8_t buffer[SSL3_RT_MAX_PLAIN_LENGTH]
Encrypted data read from the next bio.
Definition tls.c:96
static int fr_bio_tls_shutdown(fr_bio_t *bio)
Disconnect the bio from the fd.
Definition tls.c:712
fr_tls_connection_t * conn
The TLS connection, which is a child of the bio.
Definition tls.c:68
static size_t fr_bio_tls_clean_read(fr_bio_tls_t *my, void *buffer, size_t size)
Copy decrypted data which the caller has not yet read into the caller's buffer.
Definition tls.c:536
static int fr_bio_tls_destructor(fr_bio_tls_t *my)
Send any close_notify, stop the fd events, cancel the request, and then run the common bio destructor...
Definition tls.c:991
static int fr_bio_tls_handshake_start(fr_bio_tls_t *my)
The fd is connected, so start the TLS connection.
Definition tls.c:831
static ssize_t fr_bio_tls_conn_write(fr_tls_connection_t *conn, uint8_t const *data, size_t size)
Write encrypted records to the next bio.
Definition tls.c:198
static fr_bio_tls_t * fr_bio_tls_from_fd(fr_bio_t *fd_bio)
Find the TLS bio from the fd bio.
Definition tls.c:906
static void fr_bio_tls_next_resume(fr_bio_t *next)
Tell the next bio that it can write again.
Definition tls.c:155
fr_event_list_t * el
The event list of the interpreter.
Definition tls.c:71
static fr_event_update_t const pause_write[]
Definition tls.c:99
static ssize_t fr_bio_tls_write(fr_bio_t *bio, void *packet_ctx, void const *buffer, size_t size)
Definition tls.c:446
The TLS bio.
Definition tls.c:65
static int packet_ctx
the tests pass only the address of packet_ctx
static uint8_t request[4]
static void fr_bio_chain(fr_bio_t *first, fr_bio_t *second)
Chain one bio after another.
Definition bio_priv.h:86
#define UNUSED
Definition build.h:415
#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...
Definition dbuff.h:819
#define fr_dbuff_start(_dbuff_or_marker)
Return the 'start' position of a dbuff or marker.
Definition dbuff.h:950
#define fr_dbuff_extend_lowat(_status, _dbuff_or_marker, _lowat)
Extend if we're below _lowat.
Definition dbuff.h:712
#define fr_dbuff_remaining(_dbuff_or_marker)
Return the number of bytes remaining between the dbuff or marker and the end of the buffer.
Definition dbuff.h:795
#define fr_dbuff_in_memcpy(_dbuff_or_marker, _in, _inlen)
Copy exactly _inlen bytes into a dbuff or marker.
Definition dbuff.h:1403
#define fr_event_fd_insert(...)
Definition event.h:247
#define fr_event_filter_update(...)
Definition event.h:239
#define FR_EVENT_RESUME(_s, _f)
Re-add the filter for a func from kevent.
Definition event.h:131
#define FR_EVENT_SUSPEND(_s, _f)
Temporarily remove the filter for a func from kevent.
Definition event.h:115
@ FR_EVENT_FILTER_IO
Combined filter for read/write functions/.
Definition event.h:83
Callbacks for the FR_EVENT_FILTER_IO filter.
Definition event.h:188
Structure describing a modification to a filter's state.
Definition event.h:96
int fr_bio_fd_connect_full(fr_bio_t *bio, fr_event_list_t *el, fr_bio_callback_t connected_cb, fr_bio_callback_t error_cb, fr_time_delta_t *timeout, fr_bio_callback_t timeout_cb)
Finalize a connect()
Definition fd.c:1349
fr_bio_fd_info_t const * fr_bio_fd_info(fr_bio_t *bio)
Returns a pointer to the bio-specific information.
Definition fd.c:1446
fr_socket_t socket
as connected socket
Definition fd.h:145
char const * name
printable name of this BIO
Definition fd.h:150
bool eof
are we at EOF?
Definition fd.h:154
fr_bio_fd_state_t state
connecting, open, closed, etc.
Definition fd.h:148
@ FR_BIO_FD_STATE_OPEN
error states must be before this
Definition fd.h:54
Run-time status of the socket.
Definition fd.h:144
talloc_free(hp)
rlm_rcode_t unlang_interpret(request_t *request, bool running)
Run the interpreter for a current request.
Definition interpret.c:1302
#define SHUTDOWN
Definition interpret.c:2530
void unlang_interpret_signal(request_t *request, fr_signal_t action)
Send a signal (usually stop) to a request.
Definition interpret.c:1794
fr_event_list_t * unlang_interpret_event_list(request_t *request)
Get the event list for the current interpreter.
Definition interpret.c:2778
#define UNLANG_REQUEST_RESUME
Definition interpret.h:48
int fr_bio_write_blocked(fr_bio_t *bio)
Internal BIO function to tell all BIOs that it's blocked.
Definition base.c:354
ssize_t fr_bio_shutdown_read(UNUSED fr_bio_t *bio, UNUSED void *packet_ctx, UNUSED void *buffer, UNUSED size_t size)
Definition base.c:74
int fr_bio_destructor(fr_bio_t *bio)
Free this bio.
Definition base.c:35
ssize_t fr_bio_shutdown_write(UNUSED fr_bio_t *bio, UNUSED void *packet_ctx, UNUSED void const *buffer, UNUSED size_t size)
Definition base.c:79
fr_bio_t * fr_bio_eof(fr_bio_t *bio)
Internal BIO function to run EOF callbacks.
Definition base.c:280
int fr_bio_shutdown(fr_bio_t *bio)
Shut down a set of BIOs.
Definition base.c:158
int fr_event_fd_delete(fr_event_list_t *el, int fd, fr_event_filter_t filter)
Remove a file descriptor from the event loop.
Definition event.c:1204
Stores all information relating to an event list.
Definition event.c:375
long int ssize_t
unsigned char uint8_t
static size_t used
#define fr_assert(_expr)
Definition rad_assert.h:37
@ FR_SIGNAL_CANCEL
Request has been cancelled.
Definition signal.h:40
#define talloc_asprintf
Definition talloc.h:151
static fr_event_list_t * el
int fd
File descriptor if this is a live socket.
Definition socket.h:86
int type
SOCK_STREAM, SOCK_DGRAM, etc.
Definition socket.h:84
#define fr_strerror_const_push(_msg)
Definition strerror.h:227
#define fr_strerror_const(_msg)
Definition strerror.h:223
static fr_slen_t data
Definition value.h:1366