The FreeRADIUS server $Id: a4e7f8c94e8038b7627bcf52356b7ed15955c1d7 $
Loading...
Searching...
No Matches
unit_test_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
5 * (at 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 * $Id: 918d4fc82532ce7a4786c7ac0d9fe3eae5609f11 $
18 *
19 * @file unit_test_tls.c
20 * @brief TLS server test framework
21 *
22 * This program loads the "tls" protocol and reads two top-level sections
23 * from unit_test_tls.conf. The "tls" section supplies the TLS server
24 * context, and takes exactly the items that a TLS configuration takes
25 * anywhere else in the server. The "unit_test_tls" section supplies what
26 * steers the test program itself, which is the address of the listening TCP
27 * socket and whether a client certificate is required.
28 *
29 * One connection is accepted, and the TLS handshake for that connection is
30 * run to completion.
31 *
32 * The handshake runs on a persistent asynchronous interpreter, the same way
33 * radiusd runs one. A persistent interpreter keeps the handshake state
34 * across the several rounds of a single connection.
35 *
36 * The "virtual_server" item in the "tls" section names a virtual server.
37 * That virtual server supplies the "verify certificate", "load session",
38 * "store session" and "clear session" sections which the handshake calls.
39 *
40 * To run the test, start unit_test_tls with the test configuration, then
41 * connect to the listening socket:
42 *
43 * @code
44 * ./scripts/bin/unit_test_tls -d src/tests/tls -X
45 *
46 * openssl s_client -connect 127.0.0.1:2083 \
47 * -cert raddb/certs/rsa/client.pem \
48 * -key raddb/certs/rsa/client.key -pass pass:whatever \
49 * -CAfile raddb/certs/rsa/ca.pem
50 * @endcode
51 *
52 * src/tests/tls/unit_test_tls.conf documents every configuration item.
53 *
54 * @copyright 2025 The FreeRADIUS server project
55 */
56RCSID("$Id: 918d4fc82532ce7a4786c7ac0d9fe3eae5609f11 $")
57
58#include <freeradius-devel/server/base.h>
59#include <freeradius-devel/server/module_rlm.h>
60
61#include <freeradius-devel/io/listen.h>
62#include <freeradius-devel/io/thread.h>
63
64#include <freeradius-devel/tls/base.h>
65#include <freeradius-devel/tls/dtls.h>
66#include <freeradius-devel/tls/strerror.h>
67#include <freeradius-devel/tls/version.h>
68#include <freeradius-devel/tls/connection.h>
69#include <freeradius-devel/util/misc.h>
70
71#include <freeradius-devel/unlang/base.h>
72#include <freeradius-devel/unlang/function.h>
73#include <freeradius-devel/unlang/interpret.h>
74
75#include <freeradius-devel/util/socket.h>
76
77#include <freeradius-devel/protocol/freeradius/freeradius.internal.h>
78
79#ifdef HAVE_GETOPT_H
80# include <getopt.h>
81#endif
82
83#include <sys/wait.h>
84
85#define EXIT_WITH_FAILURE \
86do { \
87 ret = EXIT_FAILURE; \
88 goto cleanup; \
89} while (0)
90
91char const *radiusd_version = RADIUSD_VERSION_BUILD("unit_test_tls");
92
94static fr_dict_t const *dict_tls;
95
98 { .out = &dict_freeradius, .proto = "freeradius" },
99 { .out = &dict_tls, .proto = "tls" },
101};
102
103/** The "unit_test_tls" section
104 *
105 * The items at the top level steer the test program and do not configure
106 * TLS. The TLS configuration for each role is a subsection.
107 * `fr_tls_server_config` and `fr_tls_client_config` parse the subsections,
108 * so each subsection takes exactly the items that a `tls { ... }` section
109 * takes anywhere else in the server.
110 */
111/** One transport's socket, named by `transport` in the configuration
112 *
113 */
114typedef struct {
115 fr_ipaddr_t ipaddr; //!< Address of the listening socket.
116 uint16_t port; //!< Port of the listening socket.
118
119typedef struct {
120 char const *transport; //!< "tcp" or "udp", naming the subsection below
121 ///< which holds the socket.
122 int socket_type; //!< SOCK_STREAM or SOCK_DGRAM, from `transport`.
123
124 unit_test_tls_socket_t tcp; //!< The `tcp { ... }` subsection.
125 unit_test_tls_socket_t udp; //!< The `udp { ... }` subsection.
126
127 fr_ipaddr_t ipaddr; //!< Address of the listening socket, copied from
128 ///< whichever subsection `transport` named.
129 uint16_t port; //!< Port of the listening socket, and the default
130 ///< port for -s.
131 uint32_t drop_datagram; //!< Drop this datagram rather than sending it,
132 ///< counting from one. Zero drops nothing.
133 bool require_client_certificate; //!< Whether the client has to present a certificate.
134
135 fr_tls_conf_t *server; //!< The `server { ... }` subsection.
136 fr_tls_conf_t *client; //!< The `client { ... }` subsection, used with `-s`.
138
139/** The socket items, parsed once per transport subsection
140 *
141 */
151
153 /*
154 * `transport` names a subsection, the way a listener's
155 * `transport` does, see common_transport_parse() in
156 * src/lib/bio/fd_config.c. The socket items live in that
157 * subsection rather than here, so that a configuration which
158 * names one transport cannot carry another one's settings.
159 */
160 { FR_CONF_OFFSET("transport", unit_test_tls_conf_t, transport), .dflt = "tcp" },
161
166
167 /*
168 * Lose a datagram on purpose, so that a test can see the
169 * retransmission which recovers from it. Zero loses nothing.
170 */
171 { FR_CONF_OFFSET("drop_datagram", unit_test_tls_conf_t, drop_datagram) },
172
173 { FR_CONF_OFFSET("require_client_certificate", unit_test_tls_conf_t, require_client_certificate),
174 .dflt = "no" },
175
176 /*
177 * A test file may hold only the role that the test runs, so
178 * either subsection may be missing.
179 */
180 { FR_CONF_SUBSECTION_ALLOC("server", CONF_FLAG_OK_MISSING, unit_test_tls_conf_t, server, fr_tls_server_config),
181 .subcs_type = "fr_tls_conf_t" },
182 { FR_CONF_SUBSECTION_ALLOC("client", CONF_FLAG_OK_MISSING, unit_test_tls_conf_t, client, fr_tls_client_config),
183 .subcs_type = "fr_tls_conf_t" },
184
186};
187
188/** State of the test program
189 *
190 * The interpreter and the runnable heap live for the whole of the connection.
191 * A TLS handshake takes several rounds, and each round may yield while a
192 * virtual server section runs. The interpreter and the runnable heap
193 * therefore cannot be allocated once per round.
194 */
195typedef struct {
196 fr_event_list_t *el; //!< Event list everything runs on.
197 unlang_interpret_t *intp; //!< Interpreter for the connection.
198 fr_heap_t *runnable; //!< Requests the interpreter has marked runnable.
199 int yielded; //!< How many requests are currently yielded.
200
201 unit_test_tls_conf_t conf; //!< Parsed "unit_test_tls" section.
202 SSL_CTX *ssl_ctx; //!< Context built from the "tls" section.
203
204 fr_tls_connection_t *conn; //!< State of the connection being run.
205
206 unsigned int count; //!< How many connections to run.
207 bool alert; //!< Reject the peer with a TLS alert, see -A.
208 bool invalid; //!< Mark the session invalid mid-handshake, see -I.
209 bool nonblock; //!< Put the connection socket in non-blocking mode, see -B.
210 bool client; //!< Act as the client and connect to a server,
211 ///< rather than accept a connection. Copied into
212 ///< every connection this program allocates.
213
214 bool app_data; //!< Send one byte of application data once the
215 ///< handshake is done, see -P.
216
217 bool hold; //!< Once connected, send nothing and stay
218 ///< connected, see -H.
219
220 bool reject; //!< Reject the session once the handshake
221 ///< succeeds, see -R.
222 bool network_fail; //!< Fail the session with a network error once
223 ///< the handshake succeeds, see -N.
224 bool abort_pending; //!< Free the connection once the handshake
225 ///< succeeds, while `store session` is still
226 ///< queued, see -Q.
227 unsigned int connections; //!< How many connections have been run so far.
228 fr_ipaddr_t server_ipaddr; //!< Server named by -s.
229 uint16_t server_port; //!< Port from -s, or from the configuration.
230
231 int sockfd; //!< Listening socket.
232 fr_event_fd_t *accept_ef; //!< Read event for sockfd, while waiting in
233 ///< tls_socket_accept().
234 bool accepting; //!< Waiting in tls_socket_accept().
235
236 char const *command; //!< Command to run, see -e.
237 pid_t command_pid; //!< Command started by -e, or 0.
238 fr_event_pid_t const *command_ev; //!< Waits for the command to exit.
239 bool command_exited; //!< The command has exited.
240 bool command_waiting; //!< Waiting in tls_command_wait().
241
242 int fd; //!< Accepted or connected socket.
243
244 uint32_t datagrams; //!< How many datagrams this connection has been
245 ///< asked to write, counting from one. Only used
246 ///< by `drop_datagram`.
247
248 uint8_t *first; //!< The datagram which named the peer, read from
249 ///< the listening socket before the connection's
250 ///< socket existed. Handed to the connection once
251 ///< the connection is running.
252 size_t first_len; //!< Length of `first`.
253 fr_event_fd_t *ef; //!< Read and write events for fd.
254 bool write_blocked; //!< True while the socket has no room for a
255 ///< record and the write event is active, see
256 ///< tls_connection_write_wait().
257
258 unsigned char *alpn; //!< Protocol list built by -L, in the wire format
259 ///< fr_tls_conf_t expects. NULL means no ALPN.
260 bool alpn_required; //!< Set by -l.
261
262 bool done; //!< Set once the connection has a result.
263 int ret; //!< Exit status.
265
266static void usage(main_config_t const *config, int status);
267static void tls_request_failed(unit_test_tls_t *utt);
268
269/*
270 * Interpreter callbacks.
271 *
272 * The callbacks below mirror the set in
273 * src/lib/unlang/interpret_synchronous.c and src/lib/io/coord_pair.c. The
274 * one difference is that a post-event handler drains the runnable heap,
275 * rather than a loop inside the caller, so the event loop decides when
276 * each request runs.
277 */
278
279/** Schedule a request, once
280 *
281 * A request reaches the heap from two directions: the interpreter creating it,
282 * and the interpreter marking it runnable again. Inserting a request which is
283 * already on the heap puts it there twice, and popping it then returns a
284 * request which the heap still holds, which the interpreter refuses to run.
285 */
287{
288 if (fr_heap_entry_inserted(request->runnable)) return;
289
291}
292
293/** An internal request created by the interpreter has to run on ours
294 *
295 * The subrequests created for the "verify certificate" section and for the
296 * session cache sections reach this callback.
297 *
298 * fr_tls_call_push() pushes each of them as a detachable subrequest, which
299 * the parent waits on rather than running inline, so the subrequest has to be
300 * scheduled here or nothing ever runs it.
301 */
302static void _request_init_internal(request_t *request, void *uctx)
303{
304 unit_test_tls_t *utt = talloc_get_type_abort(uctx, unit_test_tls_t);
305
306 RDEBUG3("Initialising internal request");
307
309
310 /*
311 * interpret_child_init() calls this, and nothing else schedules
312 * the child, so a subrequest which is not put on the heap here
313 * never runs at all.
314 */
316}
317
319{
320 RDEBUG3("Done external request");
321
322 /*
323 * main() allocated the request, and the request has to survive
324 * until the connection is done with, so this callback does not
325 * free the request.
326 */
327}
328
330{
331 RDEBUG3("Done internal request");
332
333 /* The code which created the internal request frees the request */
334}
335
337{
338 RDEBUG3("Done detached request");
339
340 /*
341 * Nothing else can free a detached request, so this callback
342 * frees the detached request.
343 */
345}
346
347static void _request_detach(request_t *request, UNUSED void *uctx)
348{
349 RDEBUG3("Request detached");
350
351 if (request_detach(request) < 0) RPEDEBUG("Failed detaching request");
352}
353
354static void _request_yield(request_t *request, void *uctx)
355{
356 unit_test_tls_t *utt = talloc_get_type_abort(uctx, unit_test_tls_t);
357
358 utt->yielded++;
359
360 RDEBUG3("Request yielded");
361}
362
363static void _request_resume(request_t *request, UNUSED void *uctx)
364{
365 RDEBUG3("Request resumed");
366}
367
368static void _request_runnable(request_t *request, void *uctx)
369{
370 unit_test_tls_t *utt = talloc_get_type_abort(uctx, unit_test_tls_t);
371
372 fr_assert(utt->yielded > 0);
373 utt->yielded--;
374
376}
377
378static bool _request_scheduled(request_t const *request, UNUSED void *uctx)
379{
380 return fr_heap_entry_inserted(request->runnable);
381}
382
383/** Stop the event loop, recording why
384 *
385 * The connection carries the result, so the exit status is decided here
386 * rather than by the state machine. A process exit status is this program's
387 * notion of a result, and no part of a TLS connection should have to know
388 * about one.
389 */
390static void tls_request_close(fr_tls_connection_t *conn)
391{
392 unit_test_tls_t *utt = talloc_get_type_abort(conn->uctx, unit_test_tls_t);
393
394 if (utt->done) return;
395
396
397 utt->done = true;
398 utt->ret = conn->failed ? EXIT_FAILURE : EXIT_SUCCESS;
399
400 fr_event_loop_exit(utt->el, 1);
401}
402
403/** The connection is up, and can carry application data
404 *
405 * unit_test_tls has no application data to send, so a connection which
406 * reaches this point has done everything it was going to do. A program which
407 * did have data to send would send it here, and close when it was done.
408 */
409static void tls_request_connected(fr_tls_connection_t *conn)
410{
411 unit_test_tls_t *utt = talloc_get_type_abort(conn->uctx, unit_test_tls_t);
412
413 DEBUG2("Connection is up and can carry application data");
414
415 /*
416 * Send one byte of application data, which tells the peer that
417 * every session ticket we were going to send has already gone.
418 *
419 * This used to test fr_tls_session_is_init_finished() after
420 * every pass of the interpreter. The connected callback says
421 * the same thing and says it once, because the connection only
422 * reaches TLS_CONNECTION_CONNECTED when every ticket section has
423 * run.
424 */
425 if (utt->app_data && !conn->client) {
426 fr_tls_session_t *tls_session = conn->tls_session;
427
428 fr_dbuff_in_bytes(&tls_session->clean_in, 0x00);
429 if (fr_tls_session_send(conn->request, tls_session) < 0) {
430 ERROR("Failed encrypting the application data");
432 return;
433 }
434
435 if (fr_tls_connection_write(conn) < 0) {
436 ERROR("Failed sending the application data");
438 return;
439 }
440
441 DEBUG("Sent one byte of application data");
442 }
443
444 /*
445 * -H holds the connection open with nothing more to say. A
446 * peer which is still owed a session ticket or a byte of
447 * application data then waits for something which never
448 * arrives, which is what the post-handshake timer is for.
449 *
450 * The connection still ends: the peer gives up, closes, and
451 * this end sees EOF.
452 */
453 if (utt->hold) {
454 DEBUG("Holding the connection open, sending nothing");
455 return;
456 }
457
458 tls_request_close(conn);
459}
460
461/** Record a failure this program cannot recover from, and stop
462 *
463 * tls_request_close() reads the result from the connection, so a failure
464 * has to reach the connection before the callback runs.
465 */
467{
468 utt->conn->failed = TLS_CONNECTION_FAIL_APPLICATION;
470}
471
474 { 0 }
475};
476
479 { 0 }
480};
481
482/** Start or stop waiting for the socket to have room for more records
483 *
484 * _tls_connection_start() inserts the write event with the socket and then
485 * suspends the write event, because a socket which has room fires the write
486 * event on every pass of the event loop. tls_connection_write_wait() resumes
487 * the write event only while a record is waiting for room.
488 *
489 * A suspend reads the active callback and a resume reads the suspended
490 * callback, so a suspend and a resume have to alternate. `write_blocked`
491 * records whether the write event is active, so a suspend never follows a
492 * suspend.
493 */
495{
496 if (!utt->ef || (utt->write_blocked == wait)) return 0;
497
499 wait ? resume_write : pause_write) < 0) {
500 PERROR("Failed updating the write event for the connection");
501 return -1;
502 }
503
504 utt->write_blocked = wait;
505
506 return 0;
507}
508
509/** Write whatever OpenSSL has produced out to the connection
510 *
511 * The TLS session reads and writes memory BIOs, which are OpenSSL's in-memory
512 * I/O buffers, and never a socket. Writing each record to the socket is
513 * therefore the caller's job. The EAP code in src/lib/eap/tls.c writes
514 * records the same way.
515 */
516static ssize_t tls_connection_write(fr_tls_connection_t *conn, uint8_t const *data, size_t size)
517{
518 unit_test_tls_t *utt = talloc_get_type_abort(conn->uctx, unit_test_tls_t);
519 ssize_t slen;
520
521 /*
522 * Lose this one on purpose. Telling the connection that the
523 * whole datagram went out is what a real loss looks like from
524 * here: the sender has no idea, and only the retransmission
525 * timer recovers.
526 */
527 utt->datagrams++;
528 if (utt->conf.drop_datagram && (utt->datagrams == utt->conf.drop_datagram)) {
529 DEBUG("Dropping datagram %u of %zu bytes", utt->datagrams, size);
530 return (ssize_t) size;
531 }
532
533 /*
534 * EINTR means the write never happened, so the same octets are
535 * written again. Every other error leaves this loop.
536 */
537 for (;;) {
538 slen = write(utt->fd, data, size);
539 if (slen >= 0) break;
540
541 switch (fr_tls_connection_io_error(conn, slen)) {
542 case FR_TLS_CONNECTION_IO_RETRY:
543 continue;
544
545 case FR_TLS_CONNECTION_IO_BLOCKED:
546 /*
547 * The octets stay in the connection's buffer, and
548 * _tls_connection_write() asks the connection to
549 * write them again once the socket has room.
550 * Nothing was lost, so this is not a failure.
551 */
552 DEBUG3("Blocked writing %zu bytes to the connection", size);
553
554 if (tls_connection_write_wait(utt, true) < 0) return -1;
555 return 0;
556
557 case FR_TLS_CONNECTION_IO_EOF:
558 ERROR("Connection closed by the peer while writing to it");
559 return -1;
560
561 /*
562 * write() failed, so the classification cannot be "no
563 * error". Treat the impossible value as fatal rather
564 * than carrying on.
565 */
566 case FR_TLS_CONNECTION_IO_OK:
567 case FR_TLS_CONNECTION_IO_FATAL:
568 break;
569 }
570
571 ERROR("Failed writing to connection: %s", fr_syserror(conn->error));
572 return -1;
573 }
574
575 if (slen == 0) {
576 ERROR("Wrote no data to connection");
577 return -1;
578 }
579
580 /*
581 * Something went out, so the socket had room. Stop waiting for
582 * room, which is a no-op when we were not waiting. Whether more
583 * is queued behind this is the connection's business, not ours.
584 */
585 if (tls_connection_write_wait(utt, false) < 0) return -1;
586
587 DEBUG3("Wrote %zd bytes to the connection", slen);
588
589 return slen;
590}
591
592/** The socket is ready for writes.
593 *
594 * Run the connection state machine, which either flushes pending
595 * data, or keeps going with the next TLS state.
596 *
597 * The event loop calls _tls_connection_write() only after a write blocked,
598 * see tls_connection_write_wait().
599 */
600static void _tls_connection_write(UNUSED fr_event_list_t *el, UNUSED int fd, UNUSED int flags, void *uctx)
601{
602 unit_test_tls_t *utt = talloc_get_type_abort(uctx, unit_test_tls_t);
603
604 /*
605 * @todo - arguably remove the socket from the event list.
606 */
607 if (utt->done) return;
608
609 /*
610 * fr_tls_connection_process() writes the rest of `dirty_out` and
611 * then re-checks the connection. The re-check ends a connection
612 * whose handshake finished while a record was still queued.
613 * Calling tls_connection_write() alone would not end the
614 * connection.
615 */
616 fr_tls_connection_process(utt->conn);
617}
618
619/** A record arrived on the connection, so hand the record to the connection
620 *
621 * Reading the socket is all this program does here. Everything the record
622 * means to TLS is fr_tls_connection_recv()'s business.
623 */
624static void _tls_connection_read(UNUSED fr_event_list_t *el, int fd, UNUSED int flags, void *uctx)
625{
626 unit_test_tls_t *utt = talloc_get_type_abort(uctx, unit_test_tls_t);
627 uint8_t buf[SSL3_RT_MAX_PLAIN_LENGTH];
628 ssize_t slen;
629
630 if (utt->done) return;
631
632 slen = read(fd, buf, sizeof(buf));
633 if (slen <= 0) {
634 /*
635 * The connection records what happened, and ends itself
636 * when the result ends it. Nothing is left to do here
637 * but say which way the call was going.
638 */
639 switch (fr_tls_connection_io_error(utt->conn, slen)) {
640 /*
641 * An interrupted read and a blocked read both wait
642 * for the next read event. A socket which still
643 * holds a record fires the read event again, so
644 * returning here loses no data.
645 */
646 case FR_TLS_CONNECTION_IO_RETRY:
647 case FR_TLS_CONNECTION_IO_BLOCKED:
648 DEBUG3("Blocked reading from the connection");
649 break;
650
651 case FR_TLS_CONNECTION_IO_EOF:
652 DEBUG2("Peer closed the connection on fd %d, read returned EOF", fd);
653 break;
654
655 /*
656 * read() failed, so the classification cannot be "no
657 * error". Treat the impossible value as fatal rather
658 * than carrying on.
659 */
660 case FR_TLS_CONNECTION_IO_OK:
661 case FR_TLS_CONNECTION_IO_FATAL:
662 ERROR("Failed reading from connection: %s", fr_syserror(utt->conn->error));
663 break;
664 }
665
666 return;
667 }
668
669 fr_tls_connection_recv(utt->conn, buf, (size_t) slen);
670}
671
672/** The connection failed at the socket level
673 *
674 */
675static void _tls_connection_error(UNUSED fr_event_list_t *el, int fd, int flags, int fd_errno,
676 void *uctx)
677{
678 unit_test_tls_t *utt = talloc_get_type_abort(uctx, unit_test_tls_t);
679
680 if (fd_errno == 0) {
681 DEBUG2("Peer closed the connection on fd %d, event loop reported EOF (flags 0x%x)", fd, (unsigned int)flags);
682 (void) fr_tls_connection_io_error(utt->conn, 0);
683 return;
684 }
685
686 ERROR("Error on connection: %s", fr_syserror(fd_errno));
687
688 /*
689 * The event loop reports the error rather than leaving it in
690 * errno, so put it back where the classifier reads it.
691 */
692 errno = fd_errno;
693 (void) fr_tls_connection_io_error(utt->conn, -1);
694}
695
696/** Drain the runnable heap once per pass of the event loop
697 *
698 * A handshake round yields whenever the round runs a virtual server section.
699 * When that section finishes, unlang_interpret_mark_runnable() puts the
700 * request on the runnable heap, and this drains the heap again.
701 */
703{
704 unit_test_tls_t *utt = talloc_get_type_abort(uctx, unit_test_tls_t);
706
707 /*
708 * Stand in for an application which rejects a peer outright.
709 *
710 * `pending` says a record has arrived and the handshake has not
711 * read it yet. This hook used to live in _tls_connection_read(),
712 * where its position said the same thing, and the comment there
713 * warned that raising the alert before a record arrives sends it
714 * into an empty handshake, where it is lost. The test cannot
715 * tell: removing this test passes six suite runs out of six,
716 * because a server runs no handshake round until a record
717 * arrives. A client runs one straight away, so keep the test.
718 *
719 * Raising the alert later, with the other two hooks below, is
720 * too late. Those run after the round, and the round which
721 * would have carried the alert has gone.
722 */
723 /*
724 * Stand in for a record which FreeRADIUS itself refuses.
725 *
726 * fr_tls_session_msg_cb() marks such a session invalid and
727 * lets the round finish. The round after that refuses to
728 * continue, records FR_ERROR_VALUE_SESSION_INVALID, and sends
729 * the peer a fatal alert. Setting the flag here reaches that
730 * second round without having to feed the handshake a
731 * malformed record.
732 *
733 * `pending` places this before a round, for the same reason
734 * the alert hook below is placed there.
735 */
736 if (utt->invalid && utt->conn->tls_session && utt->conn->pending &&
737 (utt->connections == utt->count)) {
738 utt->invalid = false;
739 utt->conn->tls_session->invalid = true;
740 }
741
742 if (utt->alert && utt->conn->tls_session && utt->conn->pending &&
743 (utt->connections == utt->count)) {
744 utt->alert = false;
745
746 if (fr_tls_session_alert(utt->conn->request, utt->conn->tls_session,
747 SSL3_AL_FATAL, SSL_AD_ACCESS_DENIED) < 0) {
748 ERROR("Failed raising the TLS alert");
750 return;
751 }
752 }
753
754 while (fr_heap_pop((void **)&request, &utt->runnable) == 0) {
755 if (!request) break;
756
758
759 /*
760 * Only the connection's own request advances the
761 * handshake. A subrequest returns the subrequest's
762 * result through the interpreter.
763 *
764 * The connection's own IO is not done here any more.
765 * tls_connection_frame_process() does it, inside
766 * src/lib/tls, at the point the connection is about to
767 * wait for the peer. A real listener has no hook here,
768 * so nothing which a real listener cannot do belongs
769 * here either.
770 */
771 if (request == utt->conn->request) {
772 /*
773 * Stand in for an application which rejects a
774 * session after the handshake succeeded. The
775 * handshake has finished, so OpenSSL has asked
776 * for the session to be cached, and the
777 * connection is about to run its cache
778 * operations. Failing it here makes those
779 * operations a deny and a clear rather than a
780 * store, which is what rlm_eap_tls does when
781 * policy rejects.
782 */
783 if ((utt->reject || utt->network_fail) && (utt->connections == utt->count) &&
784 fr_tls_session_is_init_finished(utt->conn->tls_session)) {
785 INFO("%s the session after a successful handshake",
786 utt->network_fail ? "Failing, with a network error," : "Rejecting");
787
788 /*
789 * Record the reason, and nothing else.
790 * The handshake has finished, so OpenSSL
791 * has asked for the session to be cached,
792 * and the connection frame is about to run
793 * that cache work. The frame reads
794 * `failed` to decide whether the work is a
795 * store or a deny and a clear, which is
796 * what rlm_eap_tls does when policy
797 * rejects.
798 *
799 * fr_tls_connection_failed() would instead
800 * report the connection finished here, and
801 * the queued cache work would never be
802 * drained. src/lib/tls/session.c asserts
803 * on exactly that.
804 */
805 utt->conn->failed = utt->network_fail ? TLS_CONNECTION_FAIL_SYSCALL :
806 TLS_CONNECTION_FAIL_APPLICATION;
807 }
808
809 /*
810 * Free the connection while `store session` is
811 * still queued. The handshake has finished, so
812 * OpenSSL has asked for the session to be cached
813 * and the connection is about to run that work,
814 * but it has not run yet. Closing now frees the
815 * session with the operation still pending, which
816 * is the path session.c used to assert on and now
817 * discards. This is deterministic: it does not
818 * depend on when the peer closes.
819 */
820 if (utt->abort_pending && (utt->connections == utt->count) &&
821 fr_tls_session_is_init_finished(utt->conn->tls_session)) {
822 INFO("Aborting the connection with cache operations still queued");
824 return;
825 }
826 }
827
828 if (utt->done) return;
829 }
830}
831
832/** Open the listening socket described by the "unit_test_tls" section
833 *
834 */
836{
837 int sockfd;
838 fr_ipaddr_t ipaddr = utt->conf.ipaddr;
839 uint16_t port = utt->conf.port;
840
841 /*
842 * The items are not marked as required, because a client has no
843 * listening socket, and so needs neither of them.
844 */
845 if ((ipaddr.af == AF_UNSPEC) || !port) {
846 ERROR("Both 'ipaddr' and 'port' must be set in the 'unit_test_tls' section "
847 "when listening for a connection");
848 return -1;
849 }
850
851 if (utt->conf.socket_type == SOCK_DGRAM) {
852 sockfd = fr_socket_server_udp(&ipaddr, &port, NULL, false);
853 } else {
854 sockfd = fr_socket_server_tcp(&ipaddr, &port, NULL, false);
855 }
856 if (sockfd < 0) {
857 PERROR("Failed opening %s socket", utt->conf.transport);
858 return -1;
859 }
860
861 /*
862 * A datagram connection runs on its own socket bound to the
863 * same address and port as this one, see
864 * tls_socket_accept_one(). Both have to ask for the port
865 * before they bind, or the second bind fails.
866 */
867 if (utt->conf.socket_type == SOCK_DGRAM) {
868 int on = 1;
869
870 if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)) < 0) {
871 ERROR("Failed setting SO_REUSEPORT: %s", fr_syserror(errno));
872 close(sockfd);
873 return -1;
874 }
875 }
876
877 if (fr_socket_bind(sockfd, NULL, &ipaddr, &port) < 0) {
878 PERROR("Failed binding %s socket", utt->conf.transport);
879 close(sockfd);
880 return -1;
881 }
882
883 /*
884 * A datagram socket has no queue of connections to listen for.
885 * The first datagram to arrive is what stands in for a
886 * connection, see tls_socket_accept_one().
887 */
888 if ((utt->conf.socket_type == SOCK_STREAM) && (listen(sockfd, 8) < 0)) {
889 ERROR("Failed listening on TCP socket: %s", fr_syserror(errno));
890 close(sockfd);
891 return -1;
892 }
893
894 /*
895 * tls_socket_accept() waits for the socket in the event loop,
896 * and then accepts without blocking.
897 */
898 if (fr_nonblock(sockfd) < 0) {
899 PERROR("Failed setting the listening socket non-blocking");
900 close(sockfd);
901 return -1;
902 }
903
904 INFO("Listening on %pV port %u using %s", fr_box_ipaddr(ipaddr), port, utt->conf.transport);
905
906 utt->sockfd = sockfd;
907
908 return 0;
909}
910
911/** Accept a connection, if the listening socket has one queued
912 *
913 * @return
914 * - 1 if a connection was accepted.
915 * - 0 if no connection is queued.
916 * - -1 on error.
917 */
919{
920 int fd;
921
922 /*
923 * A datagram socket is not listening, so there is nothing to
924 * accept. The first ClientHello names the peer, and the
925 * connection runs on a second socket which is connect()ed to
926 * that peer: the kernel then delivers that peer's datagrams to
927 * the connected socket in preference to this one, and read()
928 * and write() work as they do on a stream.
929 *
930 * The connection cannot run on this socket. connect() is a
931 * property of the socket rather than of the descriptor, so
932 * connecting this one, or any descriptor duplicated from it,
933 * would leave the listening socket bound to one peer for the
934 * rest of the program.
935 */
936 if (utt->conf.socket_type == SOCK_DGRAM) {
937 struct sockaddr_storage peer;
938 socklen_t peerlen;
939 uint8_t buf[FR_TLS_MAX_PACKET_SIZE];
940 ssize_t slen;
941 fr_ipaddr_t ipaddr = utt->conf.ipaddr;
942 uint16_t port = utt->conf.port;
943 int on = 1;
944
945 /*
946 * Read the datagram rather than peeking at it. It is
947 * queued on this socket, and the connection's socket
948 * does not exist yet, so leaving it here would leave it
949 * somewhere the connection never reads. It is given to
950 * the connection once the connection is running, see
951 * tls_connection_run().
952 */
953 for (;;) {
954 peerlen = sizeof(peer);
955
956 slen = recvfrom(utt->sockfd, buf, sizeof(buf), 0, (struct sockaddr *) &peer, &peerlen);
957 if (slen < 0) {
958 if ((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINTR)) return 0;
959
960 ERROR("Failed reading the first datagram: %s", fr_syserror(errno));
961 return -1;
962 }
963
964 /*
965 * Filter input packets by ClientHello.
966 *
967 * Even if we connect() sockets, the connected socket could go away. Packets for
968 * that (old) socket are then received by the original accept socket. We don't
969 * know what to do with them, as the DTLS session goes away when the socket goes
970 * away.
971 *
972 * The main accept socket doesn't read its FD while the DTLS session is
973 * running, so packets might pile up here. This is only a problem for
974 * unit_test_tls, as a real server would keep reading the accept socket.
975 *
976 * @todo - keep some kind or more long-lived RBtree of client source IP/port and
977 * DTLS session. It is at least theoretically possible that we could re-liven
978 * the DTLS connection.
979 *
980 * A server which takes one of those old datagrams as a new connection request
981 * will try to start a connection to a peer which has already gone. The real
982 * peer's handshake stays queued here, and the handshake never completes.
983 *
984 * The solution (hack) is to just discard anything that doesn't look like a
985 * ClientHello.
986 *
987 * A ClientHello is a handshake record in epoch 0 whose first message is a
988 * client_hello. RFC 6347 Section 4.1 gives the record header, which is
989 * DTLS1_RT_HEADER_LENGTH octets of type, version, epoch, sequence number, and
990 * length. Section 4.3.2 gives the handshake message types. A discarded
991 * datagram looks to the peer like a lost datagram, and the peer retransmits, see
992 * Section 4.2.4.
993 */
994 if ((slen > (ssize_t) DTLS1_RT_HEADER_LENGTH) &&
995 (buf[0] == SSL3_RT_HANDSHAKE) &&
996 (buf[3] == 0) && (buf[4] == 0) &&
997 (buf[DTLS1_RT_HEADER_LENGTH] == SSL3_MT_CLIENT_HELLO)) break;
998
999 DEBUG2("Discarding a %zd byte datagram which does not start a connection", slen);
1000 }
1001
1002 fd = fr_socket_server_udp(&ipaddr, &port, NULL, false);
1003 if (fd < 0) {
1004 PERROR("Failed opening the connection's datagram socket");
1005 return -1;
1006 }
1007
1008 if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)) < 0) {
1009 ERROR("Failed setting SO_REUSEPORT: %s", fr_syserror(errno));
1010 close(fd);
1011 return -1;
1012 }
1013
1014 if (fr_socket_bind(fd, NULL, &ipaddr, &port) < 0) {
1015 PERROR("Failed binding the connection's datagram socket");
1016 close(fd);
1017 return -1;
1018 }
1019
1020 if (connect(fd, (struct sockaddr *) &peer, peerlen) < 0) {
1021 ERROR("Failed connecting to the peer: %s", fr_syserror(errno));
1022 close(fd);
1023 return -1;
1024 }
1025
1026 MEM(utt->first = talloc_memdup(utt, buf, (size_t) slen));
1027 utt->first_len = (size_t) slen;
1028
1029 utt->fd = fd;
1030
1031 return 1;
1032 }
1033
1034 fd = accept(utt->sockfd, NULL, NULL);
1035 if (fd < 0) {
1036 if ((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINTR)) return 0;
1037
1038 ERROR("Failed accepting connection: %s", fr_syserror(errno));
1039 return -1;
1040 }
1041
1042 /*
1043 * Some systems give the accepted socket the O_NONBLOCK flag of
1044 * the listening socket, and some don't. Clear it, so the socket
1045 * is blocking unless -B asks otherwise.
1046 */
1047 if (fr_blocking(fd) < 0) {
1048 PERROR("Failed setting the connection socket blocking");
1049 close(fd);
1050 return -1;
1051 }
1052
1053 utt->fd = fd;
1054
1055 return 1;
1056}
1057
1058/** Accept the connection once the listening socket is readable
1059 *
1060 */
1061static void _tls_socket_accept(fr_event_list_t *el, UNUSED int fd, UNUSED int flags, void *uctx)
1062{
1063 unit_test_tls_t *utt = talloc_get_type_abort(uctx, unit_test_tls_t);
1064
1065 if (tls_socket_accept_one(utt) == 0) return;
1066
1068}
1069
1070/** Stop waiting for a connection if the listening socket fails
1071 *
1072 */
1073static void _tls_socket_error(fr_event_list_t *el, UNUSED int fd, UNUSED int flags, int fd_errno, UNUSED void *uctx)
1074{
1075 ERROR("Listening socket failed: %s", fr_syserror(fd_errno));
1076
1078}
1079
1080/** Start waiting for a connection, from inside the event loop
1081 *
1082 * See tls_connection_run() for why this runs from inside the event loop.
1083 */
1085{
1086 unit_test_tls_t *utt = talloc_get_type_abort(uctx, unit_test_tls_t);
1087
1088 /*
1089 * The command exited before this connection, so the only
1090 * connection which can arrive is one already queued.
1091 */
1092 if (utt->command_exited) {
1093 if (tls_socket_accept_one(utt) == 0) ERROR("The command exited without connecting");
1094
1096 return;
1097 }
1098
1099 if (fr_event_fd_insert(utt, &utt->accept_ef, el, utt->sockfd,
1100 _tls_socket_accept, NULL, _tls_socket_error, utt) < 0) {
1101 PERROR("Failed adding the listening socket to the event loop");
1103 }
1104}
1105
1106/** Wait for a connection, or for the command started by -e to exit without connecting
1107 *
1108 * @return
1109 * - 0 with utt->fd set to the accepted connection.
1110 * - -1 on failure.
1111 */
1113{
1114 fr_event_user_t *ev = NULL;
1115
1116 INFO("Waiting for a connection");
1117
1118 if (fr_event_user_insert(utt, utt->el, &ev, true, _tls_socket_accept_start, utt) < 0) {
1119 PERROR("Failed scheduling the wait for a connection");
1120 return -1;
1121 }
1122
1123 utt->accepting = true;
1124 (void) fr_event_loop(utt->el);
1125 utt->accepting = false;
1126
1127 if (utt->accept_ef) {
1128 (void) fr_event_fd_delete(utt->el, utt->sockfd, FR_EVENT_FILTER_IO);
1129 utt->accept_ef = NULL;
1130 }
1131 TALLOC_FREE(ev);
1132
1133 return (utt->fd < 0) ? -1 : 0;
1134}
1135
1136/** Record that the command started by -e has exited
1137 *
1138 * If the server is waiting for a connection, a command which exits has either
1139 * connected already, and the connection is queued, or never will.
1140 */
1141static void _tls_command_exit(fr_event_list_t *el, pid_t pid, int status, void *uctx)
1142{
1143 unit_test_tls_t *utt = talloc_get_type_abort(uctx, unit_test_tls_t);
1144
1145 utt->command_exited = true;
1146
1147 if (WIFEXITED(status)) {
1148 INFO("Command (PID %ld) exited with status %d", (long)pid, WEXITSTATUS(status));
1149 } else if (WIFSIGNALED(status)) {
1150 INFO("Command (PID %ld) was killed by signal %d", (long)pid, WTERMSIG(status));
1151 }
1152
1153 if (utt->accepting) {
1154 if (tls_socket_accept_one(utt) == 0) ERROR("The command exited without connecting");
1155
1157 return;
1158 }
1159
1161}
1162
1163/** Start the command named by -e
1164 *
1165 * A server starts the command once it is listening. A command which connects
1166 * to the server connects to a socket which is already listening, so it can't
1167 * be refused, and the server sees the command exit, so it never waits for a
1168 * peer which has gone.
1169 *
1170 * A client starts the command once its first connection succeeds.
1171 */
1172static int tls_command_start(unit_test_tls_t *utt, char const *command)
1173{
1174 pid_t pid;
1175 sigset_t set;
1176
1177 pid = fork();
1178 if (pid < 0) {
1179 ERROR("Failed forking the command: %s", fr_syserror(errno));
1180 return -1;
1181 }
1182
1183 if (pid == 0) {
1184 /*
1185 * Only async-signal-safe calls between fork() and exec.
1186 * The command gets neither of our sockets, so the peer
1187 * sees the connection close when we close it, and it
1188 * gets an empty signal mask, not ours.
1189 */
1190 if (utt->sockfd >= 0) close(utt->sockfd);
1191 if (utt->fd >= 0) close(utt->fd);
1192 sigemptyset(&set);
1193 sigprocmask(SIG_SETMASK, &set, NULL);
1194 execl("/bin/sh", "sh", "-c", command, (char *)NULL);
1195 _exit(127);
1196 }
1197
1198 INFO("Started command (PID %ld): %s", (long)pid, command);
1199
1200 utt->command_pid = pid;
1201
1202 if (fr_event_pid_wait(utt, utt->el, &utt->command_ev, pid, _tls_command_exit, utt) < 0) {
1203 PERROR("Failed waiting for the command to exit");
1204 return -1;
1205 }
1206
1207 return 0;
1208}
1209
1210/** Wait for the command started by -e to exit, so its output is complete
1211 *
1212 */
1214{
1215 if (!utt->command_pid || utt->command_exited) return;
1216
1217 utt->command_waiting = true;
1218 (void) fr_event_loop(utt->el);
1219 utt->command_waiting = false;
1220}
1221
1222/** Connect to the server named by -s
1223 *
1224 */
1226{
1227 int fd;
1229
1230 fr_inet_ntop(buffer, sizeof(buffer), &utt->server_ipaddr);
1231
1232 if (utt->conf.socket_type == SOCK_DGRAM) {
1233 fd = fr_socket_client_udp(NULL, NULL, NULL, &utt->server_ipaddr, utt->server_port, false);
1234 } else {
1235 fd = fr_socket_client_tcp(NULL, NULL, &utt->server_ipaddr, utt->server_port, false);
1236 }
1237 if (fd < 0) {
1238 PERROR("Failed connecting to %s port %u", buffer, utt->server_port);
1239 return -1;
1240 }
1241
1242 INFO("Connected to %s port %u on fd %d", buffer, utt->server_port, fd);
1243
1244 utt->fd = fd;
1245
1246 return 0;
1247}
1248
1249/** Build an internal client.
1250 *
1251 * unit_test_tls accepts packets from anywhere (for now), and doesn't read "client" configuration sections.
1252 *
1253 * The client is built by allocating a CONF_SECTION rather than by filling in #fr_client_t manually, which
1254 * allows fields to be examined by `%request.client()`.
1255 *
1256 * "proto = tls" sets both the protocol and tls_required. It also fixes the
1257 * secret at "radsec", so that is the secret set here.
1258 */
1259static fr_client_t *tls_client_alloc(TALLOC_CTX *ctx, fr_ipaddr_t const *ipaddr)
1260{
1261 CONF_SECTION *cs;
1262 fr_client_t *client;
1264
1265 /*
1266 * Written without a prefix, the way a person would write it in
1267 * a "client" section. The "ipaddr" item is a COMBO_IP_PREFIX,
1268 * so a bare host address parses as a /32 or a /128.
1269 */
1270 fr_inet_ntop(buffer, sizeof(buffer), ipaddr);
1271
1272 MEM(cs = cf_section_alloc(ctx, NULL, "client", "unit_test_tls"));
1274 MEM(cf_pair_alloc(cs, "proto", "tls", T_OP_EQ, T_BARE_WORD, T_BARE_WORD));
1275 MEM(cf_pair_alloc(cs, "secret", "radsec", T_OP_EQ, T_BARE_WORD, T_DOUBLE_QUOTED_STRING));
1276 MEM(cf_pair_alloc(cs, "shortname", "unit_test_tls", T_OP_EQ, T_BARE_WORD, T_DOUBLE_QUOTED_STRING));
1277 MEM(cf_pair_alloc(cs, "nas_type", "test", T_OP_EQ, T_BARE_WORD, T_DOUBLE_QUOTED_STRING));
1278
1279 client = client_afrom_cs(ctx, cs, NULL, 0);
1280 if (!client) {
1281 PERROR("Failed creating the client for %s", buffer);
1282 talloc_free(cs);
1283 return NULL;
1284 }
1285
1286 /*
1287 * The client has to outlive the section it was built from,
1288 * because %request.client() reads the section.
1289 */
1290 talloc_steal(client, cs);
1291
1292 return client;
1293}
1294
1295/** Build the request the handshake runs under
1296 *
1297 * The TLS code reads the control list for TLS-Session-Cert-File and
1298 * TLS-Session-Require-Client-Certificate, and writes the negotiated version
1299 * and cipher suite into the session-state list, so a real request is needed.
1300 */
1301static request_t *tls_request_alloc(TALLOC_CTX *ctx, int fd, int socket_type)
1302{
1304 struct sockaddr_storage sa;
1305 socklen_t salen;
1306
1307 static uint64_t number = 0;
1308
1310 if (!request) return NULL;
1311
1312 if (!request->packet) request->packet = fr_packet_alloc(request, false);
1313 if (!request->reply) request->reply = fr_packet_alloc(request, false);
1314
1315 request->packet->timestamp = fr_time();
1316
1317 request->packet->socket.type = socket_type;
1318 request->packet->socket.fd = fd;
1319
1320 salen = sizeof(sa);
1321 if (getpeername(fd, (struct sockaddr *) &sa, &salen) == 0) {
1322 (void) fr_ipaddr_from_sockaddr(&request->packet->socket.inet.src_ipaddr,
1323 &request->packet->socket.inet.src_port, &sa, salen);
1324 request->packet->socket.af = request->packet->socket.inet.src_ipaddr.af;
1325 }
1326
1327 salen = sizeof(sa);
1328 if (getsockname(fd, (struct sockaddr *) &sa, &salen) == 0) {
1329 (void) fr_ipaddr_from_sockaddr(&request->packet->socket.inet.dst_ipaddr,
1330 &request->packet->socket.inet.dst_port, &sa, salen);
1331 }
1332
1333 /*
1334 * The client is the far end of the connection we just accepted.
1335 */
1336 request->client = tls_client_alloc(request, &request->packet->socket.inet.src_ipaddr);
1337 if (!request->client) {
1339 return NULL;
1340 }
1341
1342 request->number = number++;
1343 request->name = talloc_typed_asprintf(request, "%" PRIu64, request->number);
1344 request->master_state = REQUEST_ACTIVE;
1345
1346 request->log.dst = talloc_zero(request, log_dst_t);
1347 request->log.dst->func = vlog_request;
1348 request->log.dst->uctx = &default_log;
1349 request->log.dst->lvl = fr_debug_lvl;
1350
1351 request->log.lvl = fr_debug_lvl;
1352 request->async = talloc_zero(request, fr_async_t);
1353 request->async->request = request;
1354
1355 if (fr_packet_pairs_from_packet(request->request_ctx, &request->request_pairs, request->packet) < 0) {
1356 ERROR("Failed converting connection addresses to attributes");
1358 return NULL;
1359 }
1360
1361 return request;
1362}
1363
1364/** Add the connection to the event loop, and get it moving
1365 *
1366 * Runs from inside the event loop, see tls_connection_run().
1367 */
1369{
1370 unit_test_tls_t *utt = talloc_get_type_abort(uctx, unit_test_tls_t);
1371
1372 /*
1373 * Nothing polls. A handshake round starts when a record arrives,
1374 * and a yielded round resumes when the interpreter marks the
1375 * request runnable.
1376 *
1377 * fr_event_fd_insert() below adds the write event along with the
1378 * socket, and the call to tls_connection_write_wait() then
1379 * suspends the write event, for the reason
1380 * tls_connection_write_wait() gives.
1381 */
1382 if (fr_event_fd_insert(utt, &utt->ef, el, utt->fd,
1384 PERROR("Failed adding the connection to the event loop");
1385 tls_request_failed(utt);
1386 return;
1387 }
1388
1389 /*
1390 * fr_event_fd_insert() added the socket with the write event
1391 * active, which is the state `write_blocked` records, so set
1392 * `write_blocked` to true and then suspend the write event. No
1393 * record is waiting for room yet.
1394 */
1395 utt->write_blocked = true;
1396 if (tls_connection_write_wait(utt, false) < 0) {
1397 tls_request_failed(utt);
1398 return;
1399 }
1400
1401 /*
1402 * Run `new session { ... }` and, for a client, `load session`.
1403 * A server then waits for the ClientHello. A client has to send
1404 * it.
1405 */
1406 fr_tls_connection_wake(utt->conn);
1407}
1408
1409/** Run one connection from the first byte to the last
1410 *
1411 * Everything which belongs to a single connection is allocated here and freed
1412 * again at the end, so that the next connection starts clean. What survives
1413 * is what the cache needs: the interpreter, the modules, and so the sessions
1414 * a policy stored.
1415 */
1417{
1418 int ret = -1;
1419 fr_event_user_t *ev = NULL;
1420 request_t *stale;
1421
1422 utt->connections++;
1423
1424 /*
1425 * A connection of its own for each connection, rather than one
1426 * connection reset by hand between them. Everything the
1427 * library puts on a connection then goes when the connection
1428 * goes, and this program has nothing to remember to clear.
1429 */
1430 TALLOC_FREE(utt->conn);
1431 MEM(utt->conn = fr_tls_connection_alloc(utt, utt->el->tl,
1435 utt->conn->uctx = utt;
1436 utt->conn->client = utt->client;
1437
1438
1439
1440 utt->done = false;
1441 utt->ret = EXIT_SUCCESS;
1442 utt->fd = -1;
1443 utt->ef = NULL;
1444 utt->write_blocked = false;
1445
1446 /*
1447 * Get a connection, one way or the other.
1448 */
1449 if (utt->conn->client) {
1450 if (tls_socket_connect(utt) < 0) return -1;
1451
1452 if (utt->command && !utt->command_pid && (tls_command_start(utt, utt->command) < 0)) return -1;
1453 } else {
1454 if (tls_socket_accept(utt) < 0) return -1;
1455 }
1456
1457 /*
1458 * One place for both roles: the client has just connected,
1459 * and the server has just accepted. Neither socket inherits
1460 * the flag from the listening socket, so both are set here.
1461 */
1462 if (utt->nonblock && (fr_nonblock(utt->fd) < 0)) {
1463 PERROR("Failed setting the connection socket non-blocking");
1464 return -1;
1465 }
1466
1467 utt->conn->request = tls_request_alloc(utt, utt->fd, utt->conf.socket_type);
1468 if (!utt->conn->request) goto finish;
1469
1470 unlang_interpret_set(utt->conn->request, utt->intp);
1471
1472 /*
1473 * Name the connection for the log, now that the socket is known.
1474 * The library gives every connection a name of its own, so the
1475 * old one is freed rather than leaked. Only the application
1476 * knows what identifies a connection, which is why the library
1477 * does not do this itself.
1478 */
1479 {
1480 fr_socket_t *socket = &utt->conn->request->packet->socket;
1481
1482 talloc_const_free(utt->conn->name);
1483 utt->conn->name = fr_asprintf(utt->conn, "%s from %pV:%u to %pV:%u",
1484 (socket->type == SOCK_DGRAM) ? "DTLS" : "TLS",
1485 fr_box_ipaddr(socket->inet.src_ipaddr), socket->inet.src_port,
1486 fr_box_ipaddr(socket->inet.dst_ipaddr), socket->inet.dst_port);
1487 if (!utt->conn->name) goto finish;
1488
1489 DEBUG2("Connection is %s", utt->conn->name);
1490 }
1491
1492 /*
1493 * Both roles run the same handshake driver. Passing the request
1494 * to fr_tls_session_alloc_client() is what gives a client the
1495 * memory BIOs and the certificate validation callback which the
1496 * driver needs, see src/lib/tls/session.c.
1497 */
1498 if (utt->conn->client) {
1499 utt->conn->tls_session = fr_tls_session_alloc_client(utt->conn->request, utt->ssl_ctx, utt->conn->request);
1500 } else {
1501 INFO("Accepted connection from %pV on fd %d",
1502 fr_box_ipaddr(utt->conn->request->packet->socket.inet.src_ipaddr), utt->fd);
1503
1504 utt->conn->tls_session = fr_tls_session_alloc_server(utt->conn->request, utt->ssl_ctx, utt->conn->request,
1506 }
1507
1508 if (!utt->conn->tls_session) {
1509 PERROR("Failed creating the TLS session");
1510 goto finish;
1511 }
1512
1513 /*
1514 * Start the request with a new session, then run the
1515 * interpreter once so that the first frame yields.
1516 * unlang_interpret_mark_runnable() acts only on a
1517 * yielded frame.
1518 */
1519 /*
1520 * Bind the DTLS cookie to the socket this connection runs on.
1521 * The library hashes the whole structure with a key of its own
1522 * and never reads it, and the structure is what the rest of
1523 * the server uses to say which DTLS session a datagram belongs
1524 * to.
1525 */
1526 if (utt->conf.socket_type == SOCK_DGRAM) {
1527 utt->conn->tls_session->cookie = &utt->conn->request->packet->socket;
1528 }
1529
1530 if (fr_tls_connection_push(utt->conn) < 0) {
1531 PERROR("Failed starting new TLS connection");
1532 goto finish;
1533 }
1534
1535 (void) unlang_interpret(utt->conn->request, UNLANG_REQUEST_RESUME);
1536
1537 /*
1538 * A datagram connection starts with a datagram which was read
1539 * from the listening socket, because that is what named the
1540 * peer. The connection's socket never saw it, so hand it over
1541 * now that there is a connection to hand it to.
1542 */
1543 if (utt->first) {
1544 uint8_t *first = utt->first;
1545 size_t first_len = utt->first_len;
1546
1547 utt->first = NULL;
1548 utt->first_len = 0;
1549
1550 DEBUG3("Handing the connection the %zu byte datagram which named the peer", first_len);
1551 fr_tls_connection_recv(utt->conn, first, first_len);
1552 talloc_free(first);
1553 }
1554
1555 if (fr_event_post_insert(utt->el, _tls_runnable, utt) < 0) {
1556 PERROR("Failed adding the runnable handler to the event loop");
1557 goto finish;
1558 }
1559
1560 /*
1561 * The connection is started from inside the event loop rather
1562 * than here. Ending the previous connection left the loop
1563 * flagged as exiting, and fr_event_fd_insert() refuses to add a
1564 * socket to a loop in that state. fr_event_loop() clears the
1565 * flag as it starts, so a user event which fires immediately is
1566 * the first point at which the socket can be added.
1567 */
1568 if (fr_event_user_insert(utt, utt->el, &ev, true, _tls_connection_start, utt) < 0) {
1569 PERROR("Failed scheduling the start of the connection");
1570 goto finish;
1571 }
1572
1573 (void) fr_event_loop(utt->el);
1574
1575 ret = 0;
1576
1577finish:
1578 if (utt->ef) {
1579 (void) fr_event_fd_delete(utt->el, utt->fd, FR_EVENT_FILTER_IO);
1580 utt->ef = NULL;
1581 }
1582 (void) fr_event_post_delete(utt->el, _tls_runnable, utt);
1583
1584 /*
1585 * The user event is allocated in utt, which outlives the event
1586 * list. The destructor of the user event removes it from the
1587 * event list, so free it while the event list still exists.
1588 */
1589 TALLOC_FREE(ev);
1590
1591 /*
1592 * The connection frame is still yielded, so cancel the request to
1593 * unwind the stack before the request is freed.
1594 */
1595 if (utt->conn->request) unlang_interpret_signal(utt->conn->request, FR_SIGNAL_CANCEL);
1596
1597 /*
1598 * Empty the heap before the requests on it are freed. Popping
1599 * clears each entry's index, so nothing is left pointing at
1600 * memory the request pool is about to hand out again.
1601 */
1602 while (fr_heap_pop((void **)&stale, &utt->runnable) == 0) {
1603 if (!stale) break;
1604 }
1605 utt->yielded = 0;
1606
1607 TALLOC_FREE(utt->conn->tls_session);
1608 TALLOC_FREE(utt->conn->request);
1609
1610 if (utt->fd >= 0) {
1611 close(utt->fd);
1612 utt->fd = -1;
1613 }
1614
1615 return ret;
1616}
1617
1618/** Turn a comma separated list of names into the wire format ALPN uses
1619 *
1620 * Each name becomes one length octet followed by the name. There is no
1621 * terminator, so the caller takes the length from the array itself.
1622 *
1623 * @param[in] ctx to allocate in.
1624 * @param[in] names comma separated, in order of preference.
1625 * @return
1626 * - the list, whose talloc array length is the length of the list.
1627 * - NULL if a name is empty or longer than 255 octets.
1628 */
1629static unsigned char *tls_alpn_build(TALLOC_CTX *ctx, char const *names)
1630{
1631 unsigned char *alpn, *p;
1632 char const *q;
1633 size_t len;
1634
1635 /*
1636 * One length octet per name, and the names themselves. The
1637 * separators become those length octets, and the first name has
1638 * no separator before it, so one more octet than the string.
1639 */
1640 MEM(alpn = talloc_zero_array(ctx, unsigned char, strlen(names) + 1));
1641 p = alpn;
1642
1643 for (q = names; *q != '\0'; q += len) {
1644 len = strcspn(q, ",");
1645 if ((len == 0) || (len > 255)) {
1646 ERROR("Each ALPN protocol name must be between 1 and 255 characters");
1647 talloc_free(alpn);
1648 return NULL;
1649 }
1650
1651 *p++ = (unsigned char) len;
1652 memcpy(p, q, len);
1653 p += len;
1654
1655 if (q[len] == ',') len++; /* step over the separator */
1656 }
1657
1658 /*
1659 * A trailing separator, or a repeated one, leaves the array
1660 * longer than what was written into it. Shrink it so the array
1661 * length is the length of the list.
1662 */
1663 MEM(alpn = talloc_realloc(ctx, alpn, unsigned char, (size_t) (p - alpn)));
1664
1665 return alpn;
1666}
1667
1668int main(int argc, char *argv[])
1669{
1670 int ret = EXIT_SUCCESS;
1671 int c;
1672 char const *receipt_file = NULL;
1673 char const *command = NULL;
1674 char const *server = NULL;
1675 unsigned int count = 1;
1676 bool alert = false;
1677 bool invalid = false;
1678 bool nonblock = false;
1679 bool reject = false;
1680 bool network_fail = false;
1681 bool abort_pending = false;
1682 bool app_data = false;
1683 bool delay_tickets = false;
1684 bool hold = false;
1685 bool client = false;
1686 char const *alpn_names = NULL;
1687 bool alpn_required = false;
1688 unsigned int i;
1689
1690 TALLOC_CTX *autofree;
1691 TALLOC_CTX *thread_ctx;
1692
1693 char *p;
1695
1696 fr_dict_t *dict = NULL;
1697 fr_dict_t const *dict_check;
1698
1699 virtual_server_t const *vs;
1700 CONF_SECTION *utt_cs;
1701
1702 unit_test_tls_t *utt = NULL;
1703 fr_tls_conf_t *conf = NULL;
1704
1705 /*
1706 * Must be called first, so the handler is called last
1707 */
1709
1711 thread_ctx = talloc_new(autofree);
1712
1714 if (!config) {
1715 fr_perror("unit_test_tls");
1716 fr_exit_now(EXIT_FAILURE);
1717 }
1718
1719 p = strrchr(argv[0], FR_DIR_SEP);
1720 if (!p) {
1721 main_config_name_set_default(config, argv[0], false);
1722 } else {
1723 main_config_name_set_default(config, p + 1, false);
1724 }
1725
1727
1728 if (fr_fault_setup(autofree, getenv("PANIC_ACTION"), argv[0], PANIC_ACTION_SIGNALS) < 0) {
1729 fr_perror("%s", config->name);
1730 fr_exit_now(EXIT_FAILURE);
1731 }
1732#ifdef NDEBUG
1734#endif
1735
1736 fr_debug_lvl = 0;
1737 fr_time_start();
1738
1739 /*
1740 * The tests should have only IPs, not host names.
1741 */
1743
1744 /*
1745 * We always log to stdout.
1746 */
1748 default_log.fd = STDOUT_FILENO;
1749 default_log.print_level = true;
1750
1751 /* Process the options. */
1752 while ((c = getopt(argc, argv, "ABc:Cd:D:e:hHIlL:Mn:NPQr:Rs:TxX")) != -1) {
1753 switch (c) {
1754 case 'A':
1755 alert = true;
1756 break;
1757
1758 case 'B':
1759 nonblock = true;
1760 break;
1761
1762 case 'N':
1763 network_fail = true;
1764 break;
1765
1766 case 'R':
1767 reject = true;
1768 break;
1769
1770 case 'Q':
1771 abort_pending = true;
1772 break;
1773
1774 case 'c':
1775 count = (unsigned int) atoi(optarg);
1776 if (!count) {
1777 fprintf(stderr, "Invalid value \"%s\" for -c\n", optarg);
1778 fr_exit_now(EXIT_FAILURE);
1779 }
1780 break;
1781
1782 case 'C':
1783 check_config = true;
1784 break;
1785
1786 case 'd':
1788 break;
1789
1790 case 'D':
1792 break;
1793
1794 case 'h':
1795 usage(config, EXIT_SUCCESS);
1796 break;
1797
1798 case 'I':
1799 invalid = true;
1800 break;
1801
1802 case 'l':
1803 alpn_required = true;
1804 break;
1805
1806 case 'L':
1807 alpn_names = optarg;
1808 break;
1809
1810 case 'M':
1811 talloc_enable_leak_report();
1812 break;
1813
1814 case 'n':
1815 config->name = optarg;
1816 break;
1817
1818 case 'H':
1819 hold = true;
1820 break;
1821
1822 case 'P':
1823 app_data = true;
1824 break;
1825
1826 case 'T':
1827 delay_tickets = true;
1828 break;
1829
1830 case 'e':
1831 command = optarg;
1832 break;
1833
1834 case 'r':
1835 receipt_file = optarg;
1836 break;
1837
1838 case 's':
1839 server = optarg;
1840 break;
1841
1842 case 'X':
1843 fr_debug_lvl += 2;
1844 default_log.print_level = true;
1845 break;
1846
1847 case 'x':
1848 fr_debug_lvl++;
1849 if (fr_debug_lvl > 2) default_log.print_level = true;
1850 break;
1851
1852 default:
1853 usage(config, EXIT_FAILURE);
1854 break;
1855 }
1856 }
1857
1858 if (receipt_file && (fr_unlink(receipt_file) < 0)) {
1859 fr_perror("%s", config->name);
1861 }
1862
1863 /*
1864 * A mismatch between the OpenSSL headers used at build time and the
1865 * linked OpenSSL library makes this program exit now, rather than
1866 * crash later.
1867 */
1869
1870 /*
1871 * fr_openssl_init() must be called before *ANY* OpenSSL functions are
1872 * used, which is why
1873 * fr_openssl_init() is called so early.
1874 */
1875 if (fr_openssl_init() < 0) EXIT_WITH_FAILURE;
1876
1878
1879 /*
1880 * Mismatch between the binary and the libraries it links against
1881 */
1883 fr_perror("%s", config->name);
1885 }
1886
1887 /*
1888 * Initialise the dynamic loader infrastructure, which the config
1889 * file parser uses.
1890 */
1891 modules_init(config->lib_dir);
1892
1893 if (!fr_dict_global_ctx_init(NULL, true, config->dict_dir)) {
1894 fr_perror("%s", config->name);
1896 }
1897
1899 fr_perror("%s", config->name);
1901 }
1902
1903 if (fr_tls_dict_init() < 0) EXIT_WITH_FAILURE;
1904
1905 /*
1906 * Load the custom dictionary
1907 */
1908 if (fr_dict_read(dict, config->confdir, FR_DICTIONARY_FILE) == -1) {
1909 PERROR("Failed to initialize the dictionaries");
1911 }
1912
1914 fr_perror("%s", config->name);
1916 }
1917
1918 if (request_global_init() < 0) {
1919 fr_perror("%s", config->name);
1921 }
1922
1923 /*
1924 * The triggers are run-time expansions, so the triggers need the
1925 * main event loop.
1926 */
1927 if (main_loop_init() < 0) {
1928 PERROR("Failed initialising main event loop");
1930 }
1931
1932 if (unlang_global_init() < 0) {
1933 fr_perror("%s", config->name);
1935 }
1936
1937 if (modules_rlm_init() < 0) {
1938 fr_perror("%s", config->name);
1940 }
1941
1942 if (virtual_servers_init() < 0) {
1943 fr_perror("%s", config->name);
1945 }
1946
1948
1949 MEM(utt = talloc_zero(autofree, unit_test_tls_t));
1950 utt->sockfd = utt->fd = -1;
1951 utt->ret = EXIT_SUCCESS;
1952 utt->count = count;
1953 utt->alert = alert;
1954 utt->invalid = invalid;
1955 utt->nonblock = nonblock;
1956 utt->app_data = app_data;
1957 utt->hold = hold;
1958 utt->reject = reject;
1959 utt->network_fail = network_fail;
1960 utt->abort_pending = abort_pending;
1961
1962
1963 /*
1964 * Bootstrap and instantiate the virtual servers and the modules
1965 * that the virtual servers use. The TLS subsections name a
1966 * virtual server, so server_init() has to run before
1967 * cf_section_parse() reads the `unit_test_tls` section.
1968 */
1969 if (server_init(config->root_cs, config->confdir, dict) < 0) EXIT_WITH_FAILURE;
1970
1971 vs = virtual_server_find("tls");
1972 if (!vs) {
1973 ERROR("Cannot find virtual server 'tls'");
1975 }
1976
1977 dict_check = virtual_server_dict_by_name("tls");
1978 if (!dict_check || !fr_dict_compatible(dict_check, dict_tls)) {
1979 ERROR("Virtual server 'tls' must have 'namespace = tls'");
1981 }
1982
1983 /*
1984 * Parse the settings that steer the test program, with the TLS
1985 * configuration for each role as a subsection. The TLS rows
1986 * resolve the `virtual_server` item through
1987 * virtual_server_cf_parse(), so server_init() had to run first.
1988 * cf_section_parse_pass2() then resolves the expansions in the
1989 * TLS subsections.
1990 */
1991 utt_cs = cf_section_find(config->root_cs, "unit_test_tls", NULL);
1992 if (!utt_cs) {
1993 ERROR("Cannot find a top-level 'unit_test_tls { ... }' section in %s.conf", config->name);
1995 }
1996
1998
1999 if ((cf_section_parse(utt, &utt->conf, utt_cs) < 0) ||
2000 (cf_section_parse_pass2(&utt->conf, utt_cs) < 0)) {
2001 cf_log_perr(utt_cs, "Failed parsing the 'unit_test_tls' section");
2003 }
2004
2005 /*
2006 * Resolve `transport` into the socket it names, and into the
2007 * socket type which the TLS configuration below is given.
2008 */
2009 if (strcmp(utt->conf.transport, "tcp") == 0) {
2010 utt->conf.socket_type = SOCK_STREAM;
2011 utt->conf.ipaddr = utt->conf.tcp.ipaddr;
2012 utt->conf.port = utt->conf.tcp.port;
2013
2014 } else if (strcmp(utt->conf.transport, "udp") == 0) {
2015 utt->conf.socket_type = SOCK_DGRAM;
2016 utt->conf.ipaddr = utt->conf.udp.ipaddr;
2017 utt->conf.port = utt->conf.udp.port;
2018
2019 } else {
2020 cf_log_err(utt_cs, "Invalid transport name \"%s\", expected \"tcp\" or \"udp\"",
2021 utt->conf.transport);
2023 }
2024
2025 /*
2026 * -s turns the program around: instead of listening for a
2027 * connection, it makes one.
2028 */
2029 if (server) {
2030 utt->client = client = true;
2031
2032 if (fr_inet_pton_port(&utt->server_ipaddr, &utt->server_port, server,
2033 -1, AF_UNSPEC, true, false) < 0) {
2034 PERROR("Invalid value \"%s\" for -s", server);
2036 }
2037
2038 /*
2039 * fr_inet_pton_port() clears the port before it starts,
2040 * so a missing port is zero here, and not the default.
2041 */
2042 if (!utt->server_port) utt->server_port = utt->conf.port;
2043
2044 if (!utt->server_port) {
2045 ERROR("No port given in -s, and no 'port' in the 'unit_test_tls' section");
2047 }
2048 }
2049
2050 conf = client ? utt->conf.client : utt->conf.server;
2051 if (!conf) {
2052 cf_log_err(utt_cs, "Cannot run as %s, the 'unit_test_tls' section has no '%s { ... }' subsection",
2053 client ? "client" : "server", client ? "client" : "server");
2055 }
2056
2057 conf->delayed_tickets = delay_tickets;
2058
2059 /*
2060 * ALPN is not parsed from the configuration file. The library
2061 * leaves the protocol list to the application, so set it here,
2062 * after the TLS configuration is parsed and before the context
2063 * is built from it. See src/lib/tls/alpn.c.
2064 */
2065 if (alpn_names) {
2066 utt->alpn = tls_alpn_build(utt, alpn_names);
2067 if (!utt->alpn) EXIT_WITH_FAILURE;
2068
2069 conf->alpn = utt->alpn;
2070 conf->sizeof_alpn = talloc_array_length(utt->alpn);
2071 }
2072 conf->alpn_required = alpn_required;
2073
2074 /*
2075 * The transport is set by the application for the same reason
2076 * the ALPN strings are: one `tls { ... }` section is parsed by
2077 * the same rules everywhere, and only the application knows
2078 * what it opened the socket as.
2079 */
2080 conf->socket_type = utt->conf.socket_type;
2081
2082 utt->ssl_ctx = fr_tls_ctx_alloc(conf, client);
2083 if (!utt->ssl_ctx) {
2084 cf_log_perr(utt_cs, "Failed creating the TLS context");
2086 }
2087
2088 /*
2089 * The configuration parsed without error, so exit with success.
2090 */
2091 if (check_config) {
2092 DEBUG("Configuration appears to be OK");
2093 goto cleanup;
2094 }
2095
2096 utt->el = main_loop_event_list();
2097 fr_assert(utt->el != NULL);
2098
2099
2101
2102 /*
2103 * Simulate thread-specific instantiation
2104 */
2106 if (fr_thread_instantiate(thread_ctx, utt->el) < 0) {
2107 fr_perror("%s", config->name);
2109 }
2110
2111 if (modules_rlm_coord_attach(utt->el) < 0) {
2112 fr_perror("%s", config->name);
2114 }
2115
2116 if (fr_coord_pre_event_insert(utt->el) < 0) {
2117 fr_strerror_const("Failed adding coordinator pre-check to event list");
2119 }
2120
2121 if (fr_coord_post_event_insert(utt->el) < 0) {
2122 fr_strerror_const("Failed adding coordinator post-check to event list");
2124 }
2125
2126 /*
2127 * Set the panic action (if required)
2128 */
2129 {
2130 char const *panic_action = NULL;
2131
2132 panic_action = getenv("PANIC_ACTION");
2133 if (!panic_action) panic_action = config->panic_action;
2134
2136 fr_perror("%s", config->name);
2138 }
2139 }
2140
2141 setlinebuf(stdout); /* line buffered output */
2142
2143 /*
2144 * One interpreter, one runnable heap and one request for the
2145 * whole connection. The unit_test_tls_t documentation says why.
2146 */
2147 MEM(utt->runnable = fr_heap_talloc_alloc(utt, fr_pointer_cmp, request_t, runnable, 0));
2148
2149 utt->intp = unlang_interpret_init(utt, utt->el,
2151 .init_internal = _request_init_internal,
2152
2153 .done_external = _request_done_external,
2154 .done_internal = _request_done_internal,
2155 .done_detached = _request_done_detached,
2156
2157 .detach = _request_detach,
2158 .yield = _request_yield,
2159 .resume = _request_resume,
2160 .mark_runnable = _request_runnable,
2161 .scheduled = _request_scheduled,
2162 }, utt);
2163 if (!utt->intp) {
2164 fr_perror("%s", config->name);
2166 }
2167
2168 /*
2169 * Subrequests created by the TLS code inherit the thread default,
2170 * so the thread default has to point at the connection's
2171 * interpreter.
2172 */
2174
2175 /*
2176 * A server has one listening socket for every connection it
2177 * accepts, so it is opened once, here.
2178 */
2179 if (!utt->client && (tls_socket_open(utt) < 0)) EXIT_WITH_FAILURE;
2180
2181 /*
2182 * A server starts the command once it is listening. A client
2183 * starts it once the first connection succeeds, see
2184 * tls_connection_run().
2185 */
2186 utt->command = command;
2187 if (!utt->client && command && (tls_command_start(utt, command) < 0)) EXIT_WITH_FAILURE;
2188
2189 for (i = 0; i < utt->count; i++) {
2191
2192 if (utt->ret != EXIT_SUCCESS) break;
2193 }
2194
2195 tls_command_wait(utt);
2196
2197 ret = utt->ret;
2198
2199cleanup:
2200 if (utt) {
2201 /*
2202 * tls_connection_run() cleans up everything which belongs
2203 * to one connection. What is left here is what outlives
2204 * them.
2205 */
2206 if (utt->ssl_ctx) SSL_CTX_free(utt->ssl_ctx);
2207
2208 if (utt->sockfd >= 0) close(utt->sockfd);
2209
2210 /*
2211 * A failure left the client running. The reap below
2212 * signals it if it doesn't exit by itself.
2213 */
2214 if (utt->command_pid && !utt->command_exited) {
2216 (void) fr_event_pid_reap(utt->el, utt->command_pid, NULL, NULL);
2217 }
2218 }
2219
2221
2222 /*
2223 * Detach from coordinators.
2224 */
2225 if (utt && utt->el && (modules_rlm_coord_detach() > 0)) {
2226 if (unlikely(fr_coord_close_event_insert(utt->el) < 0)) {
2227 ERROR("Failed setting up coordinator close events");
2228 }
2229 fr_event_loop(utt->el);
2230 }
2231
2232 /*
2233 * Free thread data
2234 */
2235 talloc_free(thread_ctx);
2236
2238
2240
2241 if (utt && utt->el) fr_event_list_reap_signal(utt->el, fr_time_delta_from_sec(5), SIGKILL);
2242
2244
2246
2247 server_free();
2248
2249 /*
2250 * Virtual servers need to be freed before modules
2251 * as state entries containing data with module-specific
2252 * destructors may exist.
2253 */
2255
2257
2259
2260 fr_tls_dict_free();
2261
2263
2264 if (fr_dict_free(&dict, __FILE__) < 0) {
2265 fr_perror("unit_test_tls - dict");
2266 ret = EXIT_FAILURE;
2267 }
2268
2269 fr_openssl_free();
2270
2271 if (receipt_file && (ret == EXIT_SUCCESS) && (fr_touch(NULL, receipt_file, 0644, true, 0755) <= 0)) {
2272 fr_perror("unit_test_tls");
2273 ret = EXIT_FAILURE;
2274 }
2275
2276 if (talloc_free(autofree) < 0) {
2277 fr_perror("unit_test_tls - autofree");
2278 ret = EXIT_FAILURE;
2279 }
2280
2281 /*
2282 * Ensure our atexit handlers run before any other
2283 * atexit handlers registered by third party libraries.
2284 */
2286
2287 return ret;
2288}
2289
2290/*
2291 * Display the syntax for starting this program.
2292 */
2293static NEVER_RETURNS void usage(main_config_t const *config, int status)
2294{
2295 FILE *output = status ? stderr : stdout;
2296
2297 fprintf(output, "Usage: %s [options]\n", config->name);
2298 fprintf(output, "Options:\n");
2299 fprintf(output, " -A Reject the peer with a fatal TLS alert on the last connection,\n");
2300 fprintf(output, " rather than completing the handshake. With -c 2 the first\n");
2301 fprintf(output, " connection fills the session cache, so the alert then has a\n");
2302 fprintf(output, " session to clear. Used to test the alert and clear paths.\n");
2303 fprintf(output, " -B Put the connection socket in non-blocking mode, so that a read()\n");
2304 fprintf(output, " or a write() which would wait returns EAGAIN instead. The event\n");
2305 fprintf(output, " loop already waits for the socket to be readable or writable, so\n");
2306 fprintf(output, " this exercises the EAGAIN paths rather than changing what runs.\n");
2307 fprintf(output, " -I Mark the session invalid part way through the handshake on the\n");
2308 fprintf(output, " last connection, the way fr_tls_session_msg_cb() marks a record\n");
2309 fprintf(output, " FreeRADIUS refuses. The next round then refuses to continue, and\n");
2310 fprintf(output, " sends the peer a fatal alert saying so.\n");
2311 fprintf(output, " -R Reject the session once the handshake has succeeded on the last\n");
2312 fprintf(output, " connection, as policy would. The cached session is then cleared\n");
2313 fprintf(output, " rather than stored. With -c 2 the first connection fills the\n");
2314 fprintf(output, " cache and the second resumes from it before being rejected, so\n");
2315 fprintf(output, " the clear then has a loaded session to remove.\n");
2316 fprintf(output, " -Q Free the connection on the last connection once the handshake\n");
2317 fprintf(output, " has succeeded, while `store session` is still queued, to\n");
2318 fprintf(output, " exercise the path that discards queued cache operations.\n");
2319 fprintf(output, " -N Fail the session with a network error on the last connection,\n");
2320 fprintf(output, " once the handshake succeeds, to simulate the peer closing the\n");
2321 fprintf(output, " connection. With -c 2 the second connection loads a session\n");
2322 fprintf(output, " from the cache. A network error does not clear the loaded\n");
2323 fprintf(output, " session, and the session stays in the cache.\n");
2324 fprintf(output, " -H Once the connection is up, send nothing and hold it open.\n");
2325 fprintf(output, " A peer which is still owed a session ticket or a byte of\n");
2326 fprintf(output, " application data then waits for something which never\n");
2327 fprintf(output, " arrives, which is what exercises the post-handshake timer.\n");
2328 fprintf(output, " -c <count> Run <count> connections, one after another. Session resumption\n");
2329 fprintf(output, " needs two: one to fill the cache, one to resume from it.\n");
2330 fprintf(output, " -C Check configuration and exit.\n");
2331 fprintf(output, " -d <confdir> Configuration file directory. (defaults to " CONFDIR ").\n");
2332 fprintf(output, " -D <dict_dir> Dictionary files are in \"dict_dir/*\".\n");
2333 fprintf(output, " -e <command> Run <command> in a shell. A server runs it once it is\n");
2334 fprintf(output, " listening, so <command> can be what connects to the server,\n");
2335 fprintf(output, " such as openssl s_client. If <command> exits without\n");
2336 fprintf(output, " connecting, the server fails instead of waiting. With -s,\n");
2337 fprintf(output, " it runs once the first connection succeeds. Either way,\n");
2338 fprintf(output, " unit_test_tls waits for <command> to exit before it exits.\n");
2339 fprintf(output, " -h Print this help message.\n");
2340 fprintf(output, " -M Enable talloc leak reporting.\n");
2341 fprintf(output, " -n <name> Read ${confdir}/name.conf instead of ${confdir}/unit_test_tls.conf.\n");
2342 fprintf(output, " -P Server only. Send one byte of application data, 0x00, once the\n");
2343 fprintf(output, " handshake is done. A server sends every session ticket before\n");
2344 fprintf(output, " its first byte of application data, so this tells a client that\n");
2345 fprintf(output, " no ticket is still on its way.\n");
2346 fprintf(output, " -r <receipt_file> Create <receipt_file> when the program exits successfully.\n");
2347 fprintf(output, " -T Delay stateless TLS 1.3 session tickets, as EAP does. The server\n");
2348 fprintf(output, " sends none in the handshake.\n");
2349 fprintf(output, " -s <server[:port]> Connect to <server> as a TLS client, instead of listening\n");
2350 fprintf(output, " for a connection. Reads the 'tls client' section. The port\n");
2351 fprintf(output, " defaults to 'port' from the 'unit_test_tls' section.\n");
2352 fprintf(output, " -X Turn on full debugging.\n");
2353 fprintf(output, " -x Turn on additional debugging. (-xx gives more debugging).\n");
2354
2355 fr_exit_now(status);
2356}
static int const char char buffer[256]
Definition acutest.h:641
int fr_atexit_global_setup(void)
Setup the atexit handler, should be called at the start of a program's execution.
Definition atexit.c:179
int fr_atexit_global_trigger_all(void)
Cause all global free triggers to fire.
Definition atexit.c:310
#define fr_atexit_thread_trigger_all(...)
Definition atexit.h:236
static uint8_t request[4]
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition build.h:203
#define RCSID(id)
Definition build.h:603
#define NEVER_RETURNS
Should be placed before the function return type.
Definition build.h:413
#define unlikely(_x)
Definition build.h:486
#define UNUSED
Definition build.h:415
bool check_config
Definition cf_file.c:61
int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs)
Parse a configuration section into user-supplied variables.
Definition cf_parse.c:1360
int cf_section_parse_pass2(void *base, CONF_SECTION *cs)
Fixup xlat expansions and attributes.
Definition cf_parse.c:1470
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:722
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition cf_parse.h:280
@ CONF_FLAG_OK_MISSING
OK if it's missing.
Definition cf_parse.h:491
#define FR_CONF_SUBSECTION_ALLOC(_name, _flags, _struct, _field, _subcs)
conf_parser_t which allocates a struct and populates it from a subsection
Definition cf_parse.h:384
#define cf_section_rules_push(_cs, _rule)
Definition cf_parse.h:754
#define FR_CONF_OFFSET_SUBSECTION(_name, _flags, _struct, _field, _subcs)
conf_parser_t which populates a sub-struct using a CONF_SECTION
Definition cf_parse.h:309
#define FR_CONF_OFFSET_TYPE_FLAGS(_name, _type, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition cf_parse.h:238
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:649
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:106
CONF_PAIR * cf_pair_alloc(CONF_SECTION *parent, char const *attr, char const *value, fr_token_t op, fr_token_t lhs_quote, fr_token_t rhs_quote)
Allocate a CONF_PAIR.
Definition cf_util.c:1487
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
Definition cf_util.c:1247
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:340
#define cf_log_perr(_cf, _fmt,...)
Definition cf_util.h:347
#define cf_section_alloc(_ctx, _parent, _name1, _name2)
Definition cf_util.h:198
TALLOC_CTX * autofree
Definition common.c:29
fr_dict_t * dict
Definition common.c:31
int fr_coords_create(TALLOC_CTX *ctx, fr_event_list_t *el)
Start coordinators in single threaded mode.
Definition coord.c:619
void fr_coords_destroy(void)
Clean up coordinators in single threaded mode.
Definition coord.c:601
int fr_coord_close_event_insert(fr_event_list_t *el)
Definition coord.c:900
int fr_coord_post_event_insert(fr_event_list_t *el)
Insert instance specific post-event callbacks.
Definition coord.c:856
int fr_coord_pre_event_insert(fr_event_list_t *el)
Insert instance specific pre-event callbacks.
Definition coord.c:831
#define fr_dbuff_in_bytes(_dbuff_or_marker,...)
Copy a byte sequence into a dbuff or marker.
Definition dbuff.h:1518
static char panic_action[512]
The command to execute when panicking.
Definition debug.c:66
void fr_disable_null_tracking_on_free(TALLOC_CTX *ctx)
Disable the null tracking context when a talloc chunk is freed.
Definition debug.c:1031
void fr_talloc_fault_setup(void)
Register talloc fault handlers.
Definition debug.c:1047
int fr_fault_setup(TALLOC_CTX *ctx, char const *cmd, char const *program, unsigned long fault_signals)
Registers signal handlers to execute panic_action on fatal signal.
Definition debug.c:1071
#define PANIC_ACTION_SIGNALS
Definition debug.h:133
#define MEM(x)
Definition debug.h:38
#define fr_exit_now(_x)
Exit without calling atexit() handlers, producing a log message in debug builds.
Definition debug.h:272
void dependency_version_print(void)
Definition dependency.c:364
#define ERROR(fmt,...)
Definition dhcpclient.c:40
static int sockfd
Definition dhcpclient.c:55
#define DEBUG(fmt,...)
Definition dhcpclient.c:38
static NEVER_RETURNS void usage(void)
Definition dhcpclient.c:113
#define fr_dict_autofree(_to_free)
Definition dict.h:942
bool fr_dict_compatible(fr_dict_t const *dict1, fr_dict_t const *dict2)
See if two dictionaries have the same end parent.
Definition dict_util.c:2948
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition dict.h:329
int fr_dict_read(fr_dict_t *dict, char const *dict_dir, char const *filename))
Read supplementary attribute definitions into an existing dictionary.
int fr_dict_free(fr_dict_t **dict, char const *dependent)
Decrement the reference count on a previously loaded dictionary.
Definition dict_util.c:4466
#define fr_dict_autoload(_to_load)
Definition dict.h:939
#define DICT_AUTOLOAD_TERMINATOR
Definition dict.h:335
fr_dict_gctx_t * fr_dict_global_ctx_init(TALLOC_CTX *ctx, bool free_at_exit, char const *dict_dir))
Initialise the global protocol hashes.
Definition dict_util.c:4850
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition dict.h:328
int fr_dict_internal_afrom_file(fr_dict_t **out, char const *dict_subdir, char const *dependent)
(Re-)Initialize the special internal dictionary
#define fr_event_fd_insert(...)
Definition event.h:247
#define fr_event_filter_update(...)
Definition event.h:239
#define fr_event_pid_reap(...)
Definition event.h:274
#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
#define fr_event_pid_wait(...)
Definition event.h:268
@ FR_EVENT_FILTER_IO
Combined filter for read/write functions/.
Definition event.h:83
#define fr_event_user_insert(_ctx, _el, _ev_p, _trigger, _callback, _uctx)
Definition event.h:281
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_heap_insert(fr_heap_t **hp, void *data)
Insert a new element into the heap.
Definition heap.c:149
int fr_heap_pop(void **out, fr_heap_t **hp)
Remove a node from the heap.
Definition heap.c:359
static bool fr_heap_entry_inserted(fr_heap_index_t heap_idx)
Check if an entry is inserted into a heap.
Definition heap.h:126
#define fr_heap_talloc_alloc(_ctx, _cmp, _talloc_type, _field, _init)
Creates a heap that verifies elements are of a specific talloc type.
Definition heap.h:117
The main heap structure.
Definition heap.h:68
talloc_free(hp)
int fr_ipaddr_from_sockaddr(fr_ipaddr_t *ipaddr, uint16_t *port, struct sockaddr_storage const *sa, socklen_t salen)
Convert sockaddr to our internal ip address representation.
Definition inet.c:1448
bool fr_hostname_lookups
hostname -> IP lookups?
Definition inet.c:52
int fr_inet_pton_port(fr_ipaddr_t *out, uint16_t *port_out, char const *value, ssize_t inlen, int af, bool resolve, bool mask)
Parses IPv4/6 address + port, to fr_ipaddr_t and integer (port)
Definition inet.c:944
char * fr_inet_ntop(char out[static FR_IPADDR_STRLEN], size_t outlen, fr_ipaddr_t const *addr)
Print the address portion of a fr_ipaddr_t.
Definition inet.c:1025
bool fr_reverse_lookups
IP -> hostname lookups?
Definition inet.c:51
#define FR_IPADDR_STRLEN
Like INET6_ADDRSTRLEN but includes space for the textual Zone ID.
Definition inet.h:89
int af
Address family.
Definition inet.h:64
IPv4/6 prefix.
rlm_rcode_t unlang_interpret(request_t *request, bool running)
Run the interpreter for a current request.
Definition interpret.c:1302
void unlang_interpret_set(request_t *request, unlang_interpret_t *intp)
Set a specific interpreter for a request.
Definition interpret.c:2759
void unlang_interpret_set_thread_default(unlang_interpret_t *intp)
Set the default interpreter for this thread.
Definition interpret.c:2790
unlang_interpret_t * unlang_interpret_init(TALLOC_CTX *ctx, fr_event_list_t *el, unlang_request_func_t *funcs, void *uctx)
Initialize a unlang compiler / interpret.
Definition interpret.c:2710
void unlang_interpret_signal(request_t *request, fr_signal_t action)
Send a signal (usually stop) to a request.
Definition interpret.c:1794
#define UNLANG_REQUEST_RESUME
Definition interpret.h:48
External functions provided by the owner of the interpret.
Definition interpret.h:116
el_self ties the lifetime of the event list to the interpreter
int server_init(CONF_SECTION *cs, char const *conf_dir, fr_dict_t *dict)
Initialize src/lib/server/.
Definition base.c:42
void server_free(void)
Free src/lib/server/.
Definition base.c:137
Describes a host allowed to send packets to the server.
Definition client.h:80
void vlog_request(fr_log_type_t type, fr_log_lvl_t lvl, request_t *request, char const *file, int line, char const *fmt, va_list ap, void *uctx)
Send a log message to its destination, possibly including fields from the request.
Definition log.c:293
#define PERROR(_fmt,...)
Definition log.h:233
#define DEBUG3(_fmt,...)
Definition log.h:271
#define RDEBUG3(fmt,...)
Definition log.h:360
#define RPEDEBUG(fmt,...)
Definition log.h:393
Definition log.h:70
int fr_packet_pairs_from_packet(TALLOC_CTX *ctx, fr_pair_list_t *list, fr_packet_t const *packet)
Allocate a "Net." struct with src/dst host and port.
Definition packet.c:91
int unlang_global_init(void)
Definition base.c:158
int fr_event_post_delete(fr_event_list_t *el, fr_event_post_cb_t callback, void *uctx)
Delete a post-event callback from the event list.
Definition event.c:2066
#define fr_time()
Definition event.c:58
unsigned int fr_event_list_reap_signal(fr_event_list_t *el, fr_time_delta_t timeout, int signal)
Send a signal to all the processes we have in our reap list, and reap them.
Definition event.c:1719
void fr_event_loop_exit(fr_event_list_t *el, int code)
Signal an event loop exit with the specified code.
Definition event.c:2423
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
int fr_event_loop(fr_event_list_t *el)
Run an event loop.
Definition event.c:2445
int fr_event_post_insert(fr_event_list_t *el, fr_event_post_cb_t callback, void *uctx)
Add a post-event callback to the event list.
Definition event.c:2043
A file descriptor/filter event.
Definition event.c:258
Stores all information relating to an event list.
Definition event.c:375
Callbacks for kevent() user events.
Definition event.c:339
int fr_unlink(char const *filename)
Remove a regular file from the filesystem.
Definition file.c:366
ssize_t fr_touch(int *fd_out, char const *filename, mode_t mode, bool mkdir, mode_t dir_mode)
Create an empty file.
Definition file.c:322
int fr_debug_lvl
Definition log.c:41
fr_log_t default_log
Definition log.c:308
@ L_DST_STDOUT
Log to stdout.
Definition log.h:75
fr_packet_t * fr_packet_alloc(TALLOC_CTX *ctx, bool new_vector)
Allocate a new fr_packet_t.
Definition packet.c:38
Minimal data structure to use the new code.
Definition listen.h:79
int main_config_free(main_config_t **config)
main_config_t * main_config_alloc(TALLOC_CTX *ctx)
Allocate a main_config_t struct, setting defaults.
void main_config_name_set_default(main_config_t *config, char const *name, bool overwrite_config)
Set the server name.
int main_config_init(main_config_t *config)
void main_config_confdir_set(main_config_t *config, char const *name)
Set the global radius config directory.
void main_config_dict_dir_set(main_config_t *config, char const *name)
Set the global dictionary directory.
Main server configuration.
Definition main_config.h:59
fr_event_list_t * main_loop_event_list(void)
Return the main loop event list.
Definition main_loop.c:173
int main_loop_init(void)
Initialise the main event loop, setting up signal handlers.
Definition main_loop.c:262
void main_loop_free(void)
Definition main_loop.c:198
unsigned short uint16_t
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
@ FR_TYPE_COMBO_IP_ADDR
IPv4 or IPv6 address depending on length.
unsigned int uint32_t
long int ssize_t
unsigned char uint8_t
unsigned long int size_t
fr_cmp_ret_t fr_pointer_cmp(void const *a, void const *b)
Compares two pointers.
Definition misc.c:449
int fr_nonblock(UNUSED int fd)
Definition misc.c:293
int fr_blocking(UNUSED int fd)
Definition misc.c:298
int modules_rlm_coord_attach(fr_event_list_t *el)
Runs the coord_attach method of all registered backend modules.
Definition module_rlm.c:992
int modules_rlm_free(void)
Cleanup all global structures.
int modules_rlm_coord_detach(void)
Runs the coord_detach method of all registered backend modules.
Definition module_rlm.c:999
int modules_rlm_init(void)
Initialise the module list structure.
char * fr_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Special version of asprintf which implements custom format specifiers.
Definition print.c:883
static const conf_parser_t config[]
Definition base.c:162
#define fr_assert(_expr)
Definition rad_assert.h:37
#define DEBUG2(fmt,...)
#define INFO(fmt,...)
Definition radict.c:67
#define WIFEXITED(stat_val)
Definition radiusd.c:66
#define WEXITSTATUS(stat_val)
Definition radiusd.c:63
static bool cleanup
Definition radsniff.c:59
static rs_t * conf
Definition radsniff.c:52
rlm_rcode_t
Return codes indicating the result of the module call.
Definition rcode.h:44
int request_global_init(void)
Definition request.c:614
int request_detach(request_t *child)
Unlink a subrequest from its parent.
Definition request.c:560
#define request_local_alloc_internal(_ctx, _args)
Allocate a new internal request outside of the request pool.
Definition request.h:344
@ REQUEST_ACTIVE
Request is active (running or runnable)
Definition request.h:89
void fr_schedule_worker_id_set(int id)
Explicitly set the worker id for the current thread.
Definition schedule.c:120
@ FR_SIGNAL_CANCEL
Request has been cancelled.
Definition signal.h:40
int fr_socket_server_tcp(fr_ipaddr_t const *src_ipaddr, uint16_t *src_port, char const *port_name, bool async)
Open an IPv4/IPv6 TCP socket.
Definition socket.c:943
int fr_socket_client_udp(char const *ifname, fr_ipaddr_t *src_ipaddr, uint16_t *src_port, fr_ipaddr_t const *dst_ipaddr, uint16_t dst_port, bool async)
Establish a connected UDP socket.
Definition socket.c:611
int fr_socket_server_udp(fr_ipaddr_t const *src_ipaddr, uint16_t *src_port, char const *port_name, bool async)
Open an IPv4/IPv6 unconnected UDP socket.
Definition socket.c:841
int fr_socket_client_tcp(char const *ifname, fr_ipaddr_t *src_ipaddr, fr_ipaddr_t const *dst_ipaddr, uint16_t dst_port, bool async)
Establish a connected TCP socket.
Definition socket.c:706
int fr_socket_bind(int sockfd, char const *ifname, fr_ipaddr_t *src_ipaddr, uint16_t *src_port)
Bind a UDP/TCP v4/v6 socket to a given ipaddr src port, and interface.
Definition socket.c:200
fr_client_t * client_afrom_cs(TALLOC_CTX *ctx, CONF_SECTION *cs, CONF_SECTION *server_cs, size_t extra)
Allocate a new client from a config section.
Definition client.c:735
void modules_init(char const *lib_dir)
Perform global initialisation for modules.
Definition module.c:1981
return count
Definition module.c:155
fr_log_dst_t dst
Log destination.
Definition log.h:94
int fd
File descriptor to write messages to.
Definition log.h:109
bool print_level
sometimes we don't want log levels printed
Definition log.h:103
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition syserror.c:243
char * talloc_typed_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Call talloc vasprintf, setting the type on the new chunk correctly.
Definition talloc.c:621
static int talloc_const_free(void const *ptr)
Free const'd memory.
Definition talloc.h:289
#define talloc_autofree_context
The original function is deprecated, so replace it with our version.
Definition talloc.h:55
int fr_thread_instantiate(TALLOC_CTX *ctx, fr_event_list_t *el)
Instantiate thread-specific data for modules, virtual servers, xlats, unlang, and TLS.
Definition thread.c:177
static const char * names[8]
Definition time.c:618
int fr_time_start(void)
Initialize the local time.
Definition time.c:157
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
Definition time.h:599
"server local" time.
Definition time.h:69
int fr_openssl_version_consistent(void)
Definition version.c:246
@ T_BARE_WORD
Definition token.h:118
@ T_OP_EQ
Definition token.h:81
@ T_DOUBLE_QUOTED_STRING
Definition token.h:119
static char const * receipt_file
static fr_event_list_t * el
static void _request_yield(request_t *request, void *uctx)
uint8_t * first
The datagram which named the peer, read from the listening socket before the connection's socket exis...
unit_test_tls_socket_t udp
The udp { ... } subsection.
static int tls_socket_accept(unit_test_tls_t *utt)
Wait for a connection, or for the command started by -e to exit without connecting.
unsigned int count
How many connections to run.
unit_test_tls_socket_t tcp
The tcp { ... } subsection.
static void _request_done_external(request_t *request, UNUSED rlm_rcode_t rcode, UNUSED void *uctx)
int main(int argc, char *argv[])
static void tls_command_wait(unit_test_tls_t *utt)
Wait for the command started by -e to exit, so its output is complete.
static void _tls_runnable(UNUSED fr_event_list_t *el, UNUSED fr_time_t now, void *uctx)
Drain the runnable heap once per pass of the event loop.
unit_test_tls_conf_t conf
Parsed "unit_test_tls" section.
static void _request_resume(request_t *request, UNUSED void *uctx)
static void _tls_socket_accept_start(fr_event_list_t *el, void *uctx)
Start waiting for a connection, from inside the event loop.
SSL_CTX * ssl_ctx
Context built from the "tls" section.
bool alert
Reject the peer with a TLS alert, see -A.
uint16_t port
Port of the listening socket, and the default port for -s.
static void _request_runnable(request_t *request, void *uctx)
bool abort_pending
Free the connection once the handshake succeeds, while store session is still queued,...
static fr_client_t * tls_client_alloc(TALLOC_CTX *ctx, fr_ipaddr_t const *ipaddr)
Build an internal client.
static int tls_connection_write_wait(unit_test_tls_t *utt, bool wait)
Start or stop waiting for the socket to have room for more records.
static void _request_done_internal(request_t *request, UNUSED rlm_rcode_t rcode, UNUSED void *uctx)
int fd
Accepted or connected socket.
fr_event_list_t * el
Event list everything runs on.
fr_event_fd_t * accept_ef
Read event for sockfd, while waiting in tls_socket_accept().
bool accepting
Waiting in tls_socket_accept().
static void _tls_connection_error(UNUSED fr_event_list_t *el, int fd, int flags, int fd_errno, void *uctx)
The connection failed at the socket level.
static bool _request_scheduled(request_t const *request, UNUSED void *uctx)
bool network_fail
Fail the session with a network error once the handshake succeeds, see -N.
static void _tls_connection_read(UNUSED fr_event_list_t *el, int fd, UNUSED int flags, void *uctx)
A record arrived on the connection, so hand the record to the connection.
static fr_dict_t const * dict_freeradius
static fr_dict_t const * dict_tls
static void tls_request_close(fr_tls_connection_t *conn)
Stop the event loop, recording why.
static void tls_request_failed(unit_test_tls_t *utt)
Record a failure this program cannot recover from, and stop.
bool invalid
Mark the session invalid mid-handshake, see -I.
bool command_waiting
Waiting in tls_command_wait().
char const * command
Command to run, see -e.
static void tls_runnable_insert(unit_test_tls_t *utt, request_t *request)
Schedule a request, once.
static void _request_detach(request_t *request, UNUSED void *uctx)
fr_ipaddr_t ipaddr
Address of the listening socket.
int yielded
How many requests are currently yielded.
uint16_t port
Port of the listening socket.
bool hold
Once connected, send nothing and stay connected, see -H.
static fr_event_update_t const resume_write[]
fr_tls_connection_t * conn
State of the connection being run.
static int tls_command_start(unit_test_tls_t *utt, char const *command)
Start the command named by -e.
bool command_exited
The command has exited.
static void _tls_connection_start(fr_event_list_t *el, void *uctx)
Add the connection to the event loop, and get it moving.
static request_t * tls_request_alloc(TALLOC_CTX *ctx, int fd, int socket_type)
Build the request the handshake runs under.
bool require_client_certificate
Whether the client has to present a certificate.
fr_ipaddr_t ipaddr
Address of the listening socket, copied from whichever subsection transport named.
fr_tls_conf_t * client
The client { ... } subsection, used with -s.
bool app_data
Send one byte of application data once the handshake is done, see -P.
fr_ipaddr_t server_ipaddr
Server named by -s.
static int tls_socket_connect(unit_test_tls_t *utt)
Connect to the server named by -s.
fr_dict_autoload_t unit_test_tls_dict[]
bool reject
Reject the session once the handshake succeeds, see -R.
static void tls_request_connected(fr_tls_connection_t *conn)
The connection is up, and can carry application data.
int ret
Exit status.
char const * radiusd_version
unlang_interpret_t * intp
Interpreter for the connection.
uint32_t datagrams
How many datagrams this connection has been asked to write, counting from one.
static void _tls_connection_write(UNUSED fr_event_list_t *el, UNUSED int fd, UNUSED int flags, void *uctx)
The socket is ready for writes.
bool nonblock
Put the connection socket in non-blocking mode, see -B.
static void _tls_socket_error(fr_event_list_t *el, UNUSED int fd, UNUSED int flags, int fd_errno, UNUSED void *uctx)
Stop waiting for a connection if the listening socket fails.
fr_event_fd_t * ef
Read and write events for fd.
fr_heap_t * runnable
Requests the interpreter has marked runnable.
bool write_blocked
True while the socket has no room for a record and the write event is active, see tls_connection_writ...
char const * transport
"tcp" or "udp", naming the subsection below which holds the socket.
#define EXIT_WITH_FAILURE
fr_event_pid_t const * command_ev
Waits for the command to exit.
static void _tls_command_exit(fr_event_list_t *el, pid_t pid, int status, void *uctx)
Record that the command started by -e has exited.
bool alpn_required
Set by -l.
static int tls_socket_open(unit_test_tls_t *utt)
Open the listening socket described by the "unit_test_tls" section.
static void _tls_socket_accept(fr_event_list_t *el, UNUSED int fd, UNUSED int flags, void *uctx)
Accept the connection once the listening socket is readable.
int sockfd
Listening socket.
unsigned int connections
How many connections have been run so far.
static int tls_socket_accept_one(unit_test_tls_t *utt)
Accept a connection, if the listening socket has one queued.
unsigned char * alpn
Protocol list built by -L, in the wire format fr_tls_conf_t expects.
static ssize_t tls_connection_write(fr_tls_connection_t *conn, uint8_t const *data, size_t size)
Write whatever OpenSSL has produced out to the connection.
static void _request_done_detached(request_t *request, UNUSED rlm_rcode_t rcode, UNUSED void *uctx)
size_t first_len
Length of first.
bool done
Set once the connection has a result.
bool client
Act as the client and connect to a server, rather than accept a connection.
int socket_type
SOCK_STREAM or SOCK_DGRAM, from transport.
static const conf_parser_t unit_test_tls_socket_config[]
The socket items, parsed once per transport subsection.
static const conf_parser_t unit_test_tls_config[]
pid_t command_pid
Command started by -e, or 0.
fr_tls_conf_t * server
The server { ... } subsection.
static void _request_init_internal(request_t *request, void *uctx)
An internal request created by the interpreter has to run on ours.
uint32_t drop_datagram
Drop this datagram rather than sending it, counting from one.
static fr_event_update_t const pause_write[]
static int tls_connection_run(unit_test_tls_t *utt)
Run one connection from the first byte to the last.
uint16_t server_port
Port from -s, or from the configuration.
static unsigned char * tls_alpn_build(TALLOC_CTX *ctx, char const *names)
Turn a comma separated list of names into the wire format ALPN uses.
The "unit_test_tls" section.
State of the test program.
#define FR_DICTIONARY_FILE
Definition conf.h:6
#define FR_DICTIONARY_INTERNAL_DIR
Definition conf.h:7
int type
SOCK_STREAM, SOCK_DGRAM, etc.
Definition socket.h:84
Holds information necessary for binding or connecting to a socket.
Definition socket.h:60
void fr_perror(char const *fmt,...)
Print the current error to stderr with a prefix.
Definition strerror.c:737
#define fr_strerror_const(_msg)
Definition strerror.h:223
int fr_check_lib_magic(uint64_t magic)
Check if the application linking to the library has the correct magic number.
Definition version.c:40
#define RADIUSD_VERSION_BUILD(_x)
Create a version string for a utility in the suite of FreeRADIUS utilities.
Definition version.h:58
#define RADIUSD_MAGIC_NUMBER
Definition version.h:81
#define fr_box_ipaddr(_val)
Definition value.h:348
static fr_slen_t data
Definition value.h:1366
static fr_sbuff_err_t char size_t * len
Definition value.h:1061
fr_dict_t const * virtual_server_dict_by_name(char const *virtual_server)
Return the namespace for the named virtual server.
virtual_server_t const * virtual_server_find(char const *name)
Return virtual server matching the specified name.
int virtual_servers_init(void)
Performs global initialisation for the virtual server code.
int virtual_servers_free(void)