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: ac9e3b96ecde1e3405ad102219a7cec5a29fd567 $
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: ac9e3b96ecde1e3405ad102219a7cec5a29fd567 $")
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 unsigned int connections; //!< How many connections have been run so far.
223 fr_ipaddr_t server_ipaddr; //!< Server named by -s.
224 uint16_t server_port; //!< Port from -s, or from the configuration.
225
226 int sockfd; //!< Listening socket.
227 fr_event_fd_t *accept_ef; //!< Read event for sockfd, while waiting in
228 ///< tls_socket_accept().
229 bool accepting; //!< Waiting in tls_socket_accept().
230
231 char const *command; //!< Command to run, see -e.
232 pid_t command_pid; //!< Command started by -e, or 0.
233 fr_event_pid_t const *command_ev; //!< Waits for the command to exit.
234 bool command_exited; //!< The command has exited.
235 bool command_waiting; //!< Waiting in tls_command_wait().
236
237 int fd; //!< Accepted or connected socket.
238
239 uint32_t datagrams; //!< How many datagrams this connection has been
240 ///< asked to write, counting from one. Only used
241 ///< by `drop_datagram`.
242
243 uint8_t *first; //!< The datagram which named the peer, read from
244 ///< the listening socket before the connection's
245 ///< socket existed. Handed to the connection once
246 ///< the connection is running.
247 size_t first_len; //!< Length of `first`.
248 fr_event_fd_t *ef; //!< Read and write events for fd.
249 bool write_blocked; //!< True while the socket has no room for a
250 ///< record and the write event is active, see
251 ///< tls_connection_write_wait().
252
253 unsigned char *alpn; //!< Protocol list built by -L, in the wire format
254 ///< fr_tls_conf_t expects. NULL means no ALPN.
255 bool alpn_required; //!< Set by -l.
256
257 bool done; //!< Set once the connection has a result.
258 int ret; //!< Exit status.
260
261static void usage(main_config_t const *config, int status);
262static void tls_request_failed(unit_test_tls_t *utt);
263
264/*
265 * Interpreter callbacks.
266 *
267 * The callbacks below mirror the set in
268 * src/lib/unlang/interpret_synchronous.c and src/lib/io/coord_pair.c. The
269 * one difference is that a post-event handler drains the runnable heap,
270 * rather than a loop inside the caller, so the event loop decides when
271 * each request runs.
272 */
273
274/** Schedule a request, once
275 *
276 * A request reaches the heap from two directions: the interpreter creating it,
277 * and the interpreter marking it runnable again. Inserting a request which is
278 * already on the heap puts it there twice, and popping it then returns a
279 * request which the heap still holds, which the interpreter refuses to run.
280 */
282{
283 if (fr_heap_entry_inserted(request->runnable)) return;
284
286}
287
288/** An internal request created by the interpreter has to run on ours
289 *
290 * The subrequests created for the "verify certificate" section and for the
291 * session cache sections reach this callback.
292 *
293 * fr_tls_call_push() pushes each of them as a detachable subrequest, which
294 * the parent waits on rather than running inline, so the subrequest has to be
295 * scheduled here or nothing ever runs it.
296 */
297static void _request_init_internal(request_t *request, void *uctx)
298{
299 unit_test_tls_t *utt = talloc_get_type_abort(uctx, unit_test_tls_t);
300
301 RDEBUG3("Initialising internal request");
302
304
305 /*
306 * interpret_child_init() calls this, and nothing else schedules
307 * the child, so a subrequest which is not put on the heap here
308 * never runs at all.
309 */
311}
312
314{
315 RDEBUG3("Done external request");
316
317 /*
318 * main() allocated the request, and the request has to survive
319 * until the connection is done with, so this callback does not
320 * free the request.
321 */
322}
323
325{
326 RDEBUG3("Done internal request");
327
328 /* The code which created the internal request frees the request */
329}
330
332{
333 RDEBUG3("Done detached request");
334
335 /*
336 * Nothing else can free a detached request, so this callback
337 * frees the detached request.
338 */
340}
341
342static void _request_detach(request_t *request, UNUSED void *uctx)
343{
344 RDEBUG3("Request detached");
345
346 if (request_detach(request) < 0) RPEDEBUG("Failed detaching request");
347}
348
349static void _request_yield(request_t *request, void *uctx)
350{
351 unit_test_tls_t *utt = talloc_get_type_abort(uctx, unit_test_tls_t);
352
353 utt->yielded++;
354
355 RDEBUG3("Request yielded");
356}
357
358static void _request_resume(request_t *request, UNUSED void *uctx)
359{
360 RDEBUG3("Request resumed");
361}
362
363static void _request_runnable(request_t *request, void *uctx)
364{
365 unit_test_tls_t *utt = talloc_get_type_abort(uctx, unit_test_tls_t);
366
367 fr_assert(utt->yielded > 0);
368 utt->yielded--;
369
371}
372
373static bool _request_scheduled(request_t const *request, UNUSED void *uctx)
374{
375 return fr_heap_entry_inserted(request->runnable);
376}
377
378/** Stop the event loop, recording why
379 *
380 * The connection carries the result, so the exit status is decided here
381 * rather than by the state machine. A process exit status is this program's
382 * notion of a result, and no part of a TLS connection should have to know
383 * about one.
384 */
385static void tls_request_close(fr_tls_connection_t *conn)
386{
387 unit_test_tls_t *utt = talloc_get_type_abort(conn->uctx, unit_test_tls_t);
388
389 if (utt->done) return;
390
391
392 utt->done = true;
393 utt->ret = conn->failed ? EXIT_FAILURE : EXIT_SUCCESS;
394
395 fr_event_loop_exit(utt->el, 1);
396}
397
398/** The connection is up, and can carry application data
399 *
400 * unit_test_tls has no application data to send, so a connection which
401 * reaches this point has done everything it was going to do. A program which
402 * did have data to send would send it here, and close when it was done.
403 */
404static void tls_request_connected(fr_tls_connection_t *conn)
405{
406 unit_test_tls_t *utt = talloc_get_type_abort(conn->uctx, unit_test_tls_t);
407
408 DEBUG2("Connection is up and can carry application data");
409
410 /*
411 * Send one byte of application data, which tells the peer that
412 * every session ticket we were going to send has already gone.
413 *
414 * This used to test fr_tls_session_is_init_finished() after
415 * every pass of the interpreter. The connected callback says
416 * the same thing and says it once, because the connection only
417 * reaches TLS_CONNECTION_CONNECTED when every ticket section has
418 * run.
419 */
420 if (utt->app_data && !conn->client) {
421 fr_tls_session_t *tls_session = conn->tls_session;
422
423 fr_dbuff_in_bytes(&tls_session->clean_in, 0x00);
424 if (fr_tls_session_send(conn->request, tls_session) < 0) {
425 ERROR("Failed encrypting the application data");
427 return;
428 }
429
430 if (fr_tls_connection_write(conn) < 0) {
431 ERROR("Failed sending the application data");
433 return;
434 }
435
436 DEBUG("Sent one byte of application data");
437 }
438
439 /*
440 * -H holds the connection open with nothing more to say. A
441 * peer which is still owed a session ticket or a byte of
442 * application data then waits for something which never
443 * arrives, which is what the post-handshake timer is for.
444 *
445 * The connection still ends: the peer gives up, closes, and
446 * this end sees EOF.
447 */
448 if (utt->hold) {
449 DEBUG("Holding the connection open, sending nothing");
450 return;
451 }
452
453 tls_request_close(conn);
454}
455
456/** Record a failure this program cannot recover from, and stop
457 *
458 * tls_request_close() reads the result from the connection, so a failure
459 * has to reach the connection before the callback runs.
460 */
462{
463 utt->conn->failed = TLS_CONNECTION_FAIL_APPLICATION;
465}
466
469 { 0 }
470};
471
474 { 0 }
475};
476
477/** Start or stop waiting for the socket to have room for more records
478 *
479 * _tls_connection_start() inserts the write event with the socket and then
480 * suspends the write event, because a socket which has room fires the write
481 * event on every pass of the event loop. tls_connection_write_wait() resumes
482 * the write event only while a record is waiting for room.
483 *
484 * A suspend reads the active callback and a resume reads the suspended
485 * callback, so a suspend and a resume have to alternate. `write_blocked`
486 * records whether the write event is active, so a suspend never follows a
487 * suspend.
488 */
490{
491 if (!utt->ef || (utt->write_blocked == wait)) return 0;
492
494 wait ? resume_write : pause_write) < 0) {
495 PERROR("Failed updating the write event for the connection");
496 return -1;
497 }
498
499 utt->write_blocked = wait;
500
501 return 0;
502}
503
504/** Write whatever OpenSSL has produced out to the connection
505 *
506 * The TLS session reads and writes memory BIOs, which are OpenSSL's in-memory
507 * I/O buffers, and never a socket. Writing each record to the socket is
508 * therefore the caller's job. The EAP code in src/lib/eap/tls.c writes
509 * records the same way.
510 */
511static ssize_t tls_connection_write(fr_tls_connection_t *conn, uint8_t const *data, size_t size)
512{
513 unit_test_tls_t *utt = talloc_get_type_abort(conn->uctx, unit_test_tls_t);
514 ssize_t slen;
515
516 /*
517 * Lose this one on purpose. Telling the connection that the
518 * whole datagram went out is what a real loss looks like from
519 * here: the sender has no idea, and only the retransmission
520 * timer recovers.
521 */
522 utt->datagrams++;
523 if (utt->conf.drop_datagram && (utt->datagrams == utt->conf.drop_datagram)) {
524 DEBUG("Dropping datagram %u of %zu bytes", utt->datagrams, size);
525 return (ssize_t) size;
526 }
527
528 /*
529 * EINTR means the write never happened, so the same octets are
530 * written again. Every other error leaves this loop.
531 */
532 for (;;) {
533 slen = write(utt->fd, data, size);
534 if (slen >= 0) break;
535
536 switch (fr_tls_connection_io_error(conn, slen)) {
537 case FR_TLS_CONNECTION_IO_RETRY:
538 continue;
539
540 case FR_TLS_CONNECTION_IO_BLOCKED:
541 /*
542 * The octets stay in the connection's buffer, and
543 * _tls_connection_write() asks the connection to
544 * write them again once the socket has room.
545 * Nothing was lost, so this is not a failure.
546 */
547 DEBUG3("Blocked writing %zu bytes to the connection", size);
548
549 if (tls_connection_write_wait(utt, true) < 0) return -1;
550 return 0;
551
552 case FR_TLS_CONNECTION_IO_EOF:
553 ERROR("Connection closed by the peer while writing to it");
554 return -1;
555
556 /*
557 * write() failed, so the classification cannot be "no
558 * error". Treat the impossible value as fatal rather
559 * than carrying on.
560 */
561 case FR_TLS_CONNECTION_IO_OK:
562 case FR_TLS_CONNECTION_IO_FATAL:
563 break;
564 }
565
566 ERROR("Failed writing to connection: %s", fr_syserror(conn->error));
567 return -1;
568 }
569
570 if (slen == 0) {
571 ERROR("Wrote no data to connection");
572 return -1;
573 }
574
575 /*
576 * Something went out, so the socket had room. Stop waiting for
577 * room, which is a no-op when we were not waiting. Whether more
578 * is queued behind this is the connection's business, not ours.
579 */
580 if (tls_connection_write_wait(utt, false) < 0) return -1;
581
582 DEBUG3("Wrote %zd bytes to the connection", slen);
583
584 return slen;
585}
586
587/** The socket is ready for writes.
588 *
589 * Run the connection state machine, which either flushes pending
590 * data, or keeps going with the next TLS state.
591 *
592 * The event loop calls _tls_connection_write() only after a write blocked,
593 * see tls_connection_write_wait().
594 */
595static void _tls_connection_write(UNUSED fr_event_list_t *el, UNUSED int fd, UNUSED int flags, void *uctx)
596{
597 unit_test_tls_t *utt = talloc_get_type_abort(uctx, unit_test_tls_t);
598
599 /*
600 * @todo - arguably remove the socket from the event list.
601 */
602 if (utt->done) return;
603
604 /*
605 * fr_tls_connection_process() writes the rest of `dirty_out` and
606 * then re-checks the connection. The re-check ends a connection
607 * whose handshake finished while a record was still queued.
608 * Calling tls_connection_write() alone would not end the
609 * connection.
610 */
611 fr_tls_connection_process(utt->conn);
612}
613
614/** A record arrived on the connection, so hand the record to the connection
615 *
616 * Reading the socket is all this program does here. Everything the record
617 * means to TLS is fr_tls_connection_recv()'s business.
618 */
619static void _tls_connection_read(UNUSED fr_event_list_t *el, int fd, UNUSED int flags, void *uctx)
620{
621 unit_test_tls_t *utt = talloc_get_type_abort(uctx, unit_test_tls_t);
622 uint8_t buf[SSL3_RT_MAX_PLAIN_LENGTH];
623 ssize_t slen;
624
625 if (utt->done) return;
626
627 slen = read(fd, buf, sizeof(buf));
628 if (slen <= 0) {
629 /*
630 * The connection records what happened, and ends itself
631 * when the result ends it. Nothing is left to do here
632 * but say which way the call was going.
633 */
634 switch (fr_tls_connection_io_error(utt->conn, slen)) {
635 /*
636 * An interrupted read and a blocked read both wait
637 * for the next read event. A socket which still
638 * holds a record fires the read event again, so
639 * returning here loses no data.
640 */
641 case FR_TLS_CONNECTION_IO_RETRY:
642 case FR_TLS_CONNECTION_IO_BLOCKED:
643 DEBUG3("Blocked reading from the connection");
644 break;
645
646 case FR_TLS_CONNECTION_IO_EOF:
647 DEBUG2("Peer closed the connection on fd %d, read returned EOF", fd);
648 break;
649
650 /*
651 * read() failed, so the classification cannot be "no
652 * error". Treat the impossible value as fatal rather
653 * than carrying on.
654 */
655 case FR_TLS_CONNECTION_IO_OK:
656 case FR_TLS_CONNECTION_IO_FATAL:
657 ERROR("Failed reading from connection: %s", fr_syserror(utt->conn->error));
658 break;
659 }
660
661 return;
662 }
663
664 fr_tls_connection_recv(utt->conn, buf, (size_t) slen);
665}
666
667/** The connection failed at the socket level
668 *
669 */
670static void _tls_connection_error(UNUSED fr_event_list_t *el, int fd, int flags, int fd_errno,
671 void *uctx)
672{
673 unit_test_tls_t *utt = talloc_get_type_abort(uctx, unit_test_tls_t);
674
675 if (fd_errno == 0) {
676 DEBUG2("Peer closed the connection on fd %d, event loop reported EOF (flags 0x%x)", fd, (unsigned int)flags);
677 (void) fr_tls_connection_io_error(utt->conn, 0);
678 return;
679 }
680
681 ERROR("Error on connection: %s", fr_syserror(fd_errno));
682
683 /*
684 * The event loop reports the error rather than leaving it in
685 * errno, so put it back where the classifier reads it.
686 */
687 errno = fd_errno;
688 (void) fr_tls_connection_io_error(utt->conn, -1);
689}
690
691/** Drain the runnable heap once per pass of the event loop
692 *
693 * A handshake round yields whenever the round runs a virtual server section.
694 * When that section finishes, unlang_interpret_mark_runnable() puts the
695 * request on the runnable heap, and this drains the heap again.
696 */
698{
699 unit_test_tls_t *utt = talloc_get_type_abort(uctx, unit_test_tls_t);
701
702 /*
703 * Stand in for an application which rejects a peer outright.
704 *
705 * `pending` says a record has arrived and the handshake has not
706 * read it yet. This hook used to live in _tls_connection_read(),
707 * where its position said the same thing, and the comment there
708 * warned that raising the alert before a record arrives sends it
709 * into an empty handshake, where it is lost. The test cannot
710 * tell: removing this test passes six suite runs out of six,
711 * because a server runs no handshake round until a record
712 * arrives. A client runs one straight away, so keep the test.
713 *
714 * Raising the alert later, with the other two hooks below, is
715 * too late. Those run after the round, and the round which
716 * would have carried the alert has gone.
717 */
718 /*
719 * Stand in for a record which FreeRADIUS itself refuses.
720 *
721 * fr_tls_session_msg_cb() marks such a session invalid and
722 * lets the round finish. The round after that refuses to
723 * continue, records FR_ERROR_VALUE_SESSION_INVALID, and sends
724 * the peer a fatal alert. Setting the flag here reaches that
725 * second round without having to feed the handshake a
726 * malformed record.
727 *
728 * `pending` places this before a round, for the same reason
729 * the alert hook below is placed there.
730 */
731 if (utt->invalid && utt->conn->tls_session && utt->conn->pending &&
732 (utt->connections == utt->count)) {
733 utt->invalid = false;
734 utt->conn->tls_session->invalid = true;
735 }
736
737 if (utt->alert && utt->conn->tls_session && utt->conn->pending &&
738 (utt->connections == utt->count)) {
739 utt->alert = false;
740
741 if (fr_tls_session_alert(utt->conn->request, utt->conn->tls_session,
742 SSL3_AL_FATAL, SSL_AD_ACCESS_DENIED) < 0) {
743 ERROR("Failed raising the TLS alert");
745 return;
746 }
747 }
748
749 while (fr_heap_pop((void **)&request, &utt->runnable) == 0) {
750 if (!request) break;
751
753
754 /*
755 * Only the connection's own request advances the
756 * handshake. A subrequest returns the subrequest's
757 * result through the interpreter.
758 *
759 * The connection's own IO is not done here any more.
760 * tls_connection_frame_process() does it, inside
761 * src/lib/tls, at the point the connection is about to
762 * wait for the peer. A real listener has no hook here,
763 * so nothing which a real listener cannot do belongs
764 * here either.
765 */
766 if (request == utt->conn->request) {
767 /*
768 * Stand in for an application which rejects a
769 * session after the handshake succeeded. The
770 * handshake has finished, so OpenSSL has asked
771 * for the session to be cached, and the
772 * connection is about to run its cache
773 * operations. Failing it here makes those
774 * operations a deny and a clear rather than a
775 * store, which is what rlm_eap_tls does when
776 * policy rejects.
777 */
778 if (utt->reject && (utt->connections == utt->count) &&
779 fr_tls_session_is_init_finished(utt->conn->tls_session)) {
780 INFO("Rejecting the session after a successful handshake");
781
782 /*
783 * Record the reason, and nothing else.
784 * The handshake has finished, so OpenSSL
785 * has asked for the session to be cached,
786 * and the connection frame is about to run
787 * that cache work. The frame reads
788 * `failed` to decide whether the work is a
789 * store or a deny and a clear, which is
790 * what rlm_eap_tls does when policy
791 * rejects.
792 *
793 * fr_tls_connection_failed() would instead
794 * report the connection finished here, and
795 * the queued cache work would never be
796 * drained. src/lib/tls/session.c asserts
797 * on exactly that.
798 */
799 utt->conn->failed = TLS_CONNECTION_FAIL_APPLICATION;
800 }
801 }
802
803 if (utt->done) return;
804 }
805}
806
807/** Open the listening socket described by the "unit_test_tls" section
808 *
809 */
811{
812 int sockfd;
813 fr_ipaddr_t ipaddr = utt->conf.ipaddr;
814 uint16_t port = utt->conf.port;
815
816 /*
817 * The items are not marked as required, because a client has no
818 * listening socket, and so needs neither of them.
819 */
820 if ((ipaddr.af == AF_UNSPEC) || !port) {
821 ERROR("Both 'ipaddr' and 'port' must be set in the 'unit_test_tls' section "
822 "when listening for a connection");
823 return -1;
824 }
825
826 if (utt->conf.socket_type == SOCK_DGRAM) {
827 sockfd = fr_socket_server_udp(&ipaddr, &port, NULL, false);
828 } else {
829 sockfd = fr_socket_server_tcp(&ipaddr, &port, NULL, false);
830 }
831 if (sockfd < 0) {
832 PERROR("Failed opening %s socket", utt->conf.transport);
833 return -1;
834 }
835
836 /*
837 * A datagram connection runs on its own socket bound to the
838 * same address and port as this one, see
839 * tls_socket_accept_one(). Both have to ask for the port
840 * before they bind, or the second bind fails.
841 */
842 if (utt->conf.socket_type == SOCK_DGRAM) {
843 int on = 1;
844
845 if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)) < 0) {
846 ERROR("Failed setting SO_REUSEPORT: %s", fr_syserror(errno));
847 close(sockfd);
848 return -1;
849 }
850 }
851
852 if (fr_socket_bind(sockfd, NULL, &ipaddr, &port) < 0) {
853 PERROR("Failed binding %s socket", utt->conf.transport);
854 close(sockfd);
855 return -1;
856 }
857
858 /*
859 * A datagram socket has no queue of connections to listen for.
860 * The first datagram to arrive is what stands in for a
861 * connection, see tls_socket_accept_one().
862 */
863 if ((utt->conf.socket_type == SOCK_STREAM) && (listen(sockfd, 8) < 0)) {
864 ERROR("Failed listening on TCP socket: %s", fr_syserror(errno));
865 close(sockfd);
866 return -1;
867 }
868
869 /*
870 * tls_socket_accept() waits for the socket in the event loop,
871 * and then accepts without blocking.
872 */
873 if (fr_nonblock(sockfd) < 0) {
874 PERROR("Failed setting the listening socket non-blocking");
875 close(sockfd);
876 return -1;
877 }
878
879 INFO("Listening on %pV port %u using %s", fr_box_ipaddr(ipaddr), port, utt->conf.transport);
880
881 utt->sockfd = sockfd;
882
883 return 0;
884}
885
886/** Accept a connection, if the listening socket has one queued
887 *
888 * @return
889 * - 1 if a connection was accepted.
890 * - 0 if no connection is queued.
891 * - -1 on error.
892 */
894{
895 int fd;
896
897 /*
898 * A datagram socket is not listening, so there is nothing to
899 * accept. The first ClientHello names the peer, and the
900 * connection runs on a second socket which is connect()ed to
901 * that peer: the kernel then delivers that peer's datagrams to
902 * the connected socket in preference to this one, and read()
903 * and write() work as they do on a stream.
904 *
905 * The connection cannot run on this socket. connect() is a
906 * property of the socket rather than of the descriptor, so
907 * connecting this one, or any descriptor duplicated from it,
908 * would leave the listening socket bound to one peer for the
909 * rest of the program.
910 */
911 if (utt->conf.socket_type == SOCK_DGRAM) {
912 struct sockaddr_storage peer;
913 socklen_t peerlen;
914 uint8_t buf[FR_TLS_MAX_PACKET_SIZE];
915 ssize_t slen;
916 fr_ipaddr_t ipaddr = utt->conf.ipaddr;
917 uint16_t port = utt->conf.port;
918 int on = 1;
919
920 /*
921 * Read the datagram rather than peeking at it. It is
922 * queued on this socket, and the connection's socket
923 * does not exist yet, so leaving it here would leave it
924 * somewhere the connection never reads. It is given to
925 * the connection once the connection is running, see
926 * tls_connection_run().
927 */
928 for (;;) {
929 peerlen = sizeof(peer);
930
931 slen = recvfrom(utt->sockfd, buf, sizeof(buf), 0, (struct sockaddr *) &peer, &peerlen);
932 if (slen < 0) {
933 if ((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINTR)) return 0;
934
935 ERROR("Failed reading the first datagram: %s", fr_syserror(errno));
936 return -1;
937 }
938
939 /*
940 * Filter input packets by ClientHello.
941 *
942 * Even if we connect() sockets, the connected socket could go away. Packets for
943 * that (old) socket are then received by the original accept socket. We don't
944 * know what to do with them, as the DTLS session goes away when the socket goes
945 * away.
946 *
947 * The main accept socket doesn't read its FD while the DTLS session is
948 * running, so packets might pile up here. This is only a problem for
949 * unit_test_tls, as a real server would keep reading the accept socket.
950 *
951 * @todo - keep some kind or more long-lived RBtree of client source IP/port and
952 * DTLS session. It is at least theoretically possible that we could re-liven
953 * the DTLS connection.
954 *
955 * A server which takes one of those old datagrams as a new connection request
956 * will try to start a connection to a peer which has already gone. The real
957 * peer's handshake stays queued here, and the handshake never completes.
958 *
959 * The solution (hack) is to just discard anything that doesn't look like a
960 * ClientHello.
961 *
962 * A ClientHello is a handshake record in epoch 0 whose first message is a
963 * client_hello. RFC 6347 Section 4.1 gives the record header, which is
964 * DTLS1_RT_HEADER_LENGTH octets of type, version, epoch, sequence number, and
965 * length. Section 4.3.2 gives the handshake message types. A discarded
966 * datagram looks to the peer like a lost datagram, and the peer retransmits, see
967 * Section 4.2.4.
968 */
969 if ((slen > (ssize_t) DTLS1_RT_HEADER_LENGTH) &&
970 (buf[0] == SSL3_RT_HANDSHAKE) &&
971 (buf[3] == 0) && (buf[4] == 0) &&
972 (buf[DTLS1_RT_HEADER_LENGTH] == SSL3_MT_CLIENT_HELLO)) break;
973
974 DEBUG2("Discarding a %zd byte datagram which does not start a connection", slen);
975 }
976
977 fd = fr_socket_server_udp(&ipaddr, &port, NULL, false);
978 if (fd < 0) {
979 PERROR("Failed opening the connection's datagram socket");
980 return -1;
981 }
982
983 if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)) < 0) {
984 ERROR("Failed setting SO_REUSEPORT: %s", fr_syserror(errno));
985 close(fd);
986 return -1;
987 }
988
989 if (fr_socket_bind(fd, NULL, &ipaddr, &port) < 0) {
990 PERROR("Failed binding the connection's datagram socket");
991 close(fd);
992 return -1;
993 }
994
995 if (connect(fd, (struct sockaddr *) &peer, peerlen) < 0) {
996 ERROR("Failed connecting to the peer: %s", fr_syserror(errno));
997 close(fd);
998 return -1;
999 }
1000
1001 MEM(utt->first = talloc_memdup(utt, buf, (size_t) slen));
1002 utt->first_len = (size_t) slen;
1003
1004 utt->fd = fd;
1005
1006 return 1;
1007 }
1008
1009 fd = accept(utt->sockfd, NULL, NULL);
1010 if (fd < 0) {
1011 if ((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINTR)) return 0;
1012
1013 ERROR("Failed accepting connection: %s", fr_syserror(errno));
1014 return -1;
1015 }
1016
1017 /*
1018 * Some systems give the accepted socket the O_NONBLOCK flag of
1019 * the listening socket, and some don't. Clear it, so the socket
1020 * is blocking unless -B asks otherwise.
1021 */
1022 if (fr_blocking(fd) < 0) {
1023 PERROR("Failed setting the connection socket blocking");
1024 close(fd);
1025 return -1;
1026 }
1027
1028 utt->fd = fd;
1029
1030 return 1;
1031}
1032
1033/** Accept the connection once the listening socket is readable
1034 *
1035 */
1036static void _tls_socket_accept(fr_event_list_t *el, UNUSED int fd, UNUSED int flags, void *uctx)
1037{
1038 unit_test_tls_t *utt = talloc_get_type_abort(uctx, unit_test_tls_t);
1039
1040 if (tls_socket_accept_one(utt) == 0) return;
1041
1043}
1044
1045/** Stop waiting for a connection if the listening socket fails
1046 *
1047 */
1048static void _tls_socket_error(fr_event_list_t *el, UNUSED int fd, UNUSED int flags, int fd_errno, UNUSED void *uctx)
1049{
1050 ERROR("Listening socket failed: %s", fr_syserror(fd_errno));
1051
1053}
1054
1055/** Start waiting for a connection, from inside the event loop
1056 *
1057 * See tls_connection_run() for why this runs from inside the event loop.
1058 */
1060{
1061 unit_test_tls_t *utt = talloc_get_type_abort(uctx, unit_test_tls_t);
1062
1063 /*
1064 * The command exited before this connection, so the only
1065 * connection which can arrive is one already queued.
1066 */
1067 if (utt->command_exited) {
1068 if (tls_socket_accept_one(utt) == 0) ERROR("The command exited without connecting");
1069
1071 return;
1072 }
1073
1074 if (fr_event_fd_insert(utt, &utt->accept_ef, el, utt->sockfd,
1075 _tls_socket_accept, NULL, _tls_socket_error, utt) < 0) {
1076 PERROR("Failed adding the listening socket to the event loop");
1078 }
1079}
1080
1081/** Wait for a connection, or for the command started by -e to exit without connecting
1082 *
1083 * @return
1084 * - 0 with utt->fd set to the accepted connection.
1085 * - -1 on failure.
1086 */
1088{
1089 fr_event_user_t *ev = NULL;
1090
1091 INFO("Waiting for a connection");
1092
1093 if (fr_event_user_insert(utt, utt->el, &ev, true, _tls_socket_accept_start, utt) < 0) {
1094 PERROR("Failed scheduling the wait for a connection");
1095 return -1;
1096 }
1097
1098 utt->accepting = true;
1099 (void) fr_event_loop(utt->el);
1100 utt->accepting = false;
1101
1102 if (utt->accept_ef) {
1103 (void) fr_event_fd_delete(utt->el, utt->sockfd, FR_EVENT_FILTER_IO);
1104 utt->accept_ef = NULL;
1105 }
1106 TALLOC_FREE(ev);
1107
1108 return (utt->fd < 0) ? -1 : 0;
1109}
1110
1111/** Record that the command started by -e has exited
1112 *
1113 * If the server is waiting for a connection, a command which exits has either
1114 * connected already, and the connection is queued, or never will.
1115 */
1116static void _tls_command_exit(fr_event_list_t *el, pid_t pid, int status, void *uctx)
1117{
1118 unit_test_tls_t *utt = talloc_get_type_abort(uctx, unit_test_tls_t);
1119
1120 utt->command_exited = true;
1121
1122 if (WIFEXITED(status)) {
1123 INFO("Command (PID %ld) exited with status %d", (long)pid, WEXITSTATUS(status));
1124 } else if (WIFSIGNALED(status)) {
1125 INFO("Command (PID %ld) was killed by signal %d", (long)pid, WTERMSIG(status));
1126 }
1127
1128 if (utt->accepting) {
1129 if (tls_socket_accept_one(utt) == 0) ERROR("The command exited without connecting");
1130
1132 return;
1133 }
1134
1136}
1137
1138/** Start the command named by -e
1139 *
1140 * A server starts the command once it is listening. A command which connects
1141 * to the server connects to a socket which is already listening, so it can't
1142 * be refused, and the server sees the command exit, so it never waits for a
1143 * peer which has gone.
1144 *
1145 * A client starts the command once its first connection succeeds.
1146 */
1147static int tls_command_start(unit_test_tls_t *utt, char const *command)
1148{
1149 pid_t pid;
1150 sigset_t set;
1151
1152 pid = fork();
1153 if (pid < 0) {
1154 ERROR("Failed forking the command: %s", fr_syserror(errno));
1155 return -1;
1156 }
1157
1158 if (pid == 0) {
1159 /*
1160 * Only async-signal-safe calls between fork() and exec.
1161 * The command gets neither of our sockets, so the peer
1162 * sees the connection close when we close it, and it
1163 * gets an empty signal mask, not ours.
1164 */
1165 if (utt->sockfd >= 0) close(utt->sockfd);
1166 if (utt->fd >= 0) close(utt->fd);
1167 sigemptyset(&set);
1168 sigprocmask(SIG_SETMASK, &set, NULL);
1169 execl("/bin/sh", "sh", "-c", command, (char *)NULL);
1170 _exit(127);
1171 }
1172
1173 INFO("Started command (PID %ld): %s", (long)pid, command);
1174
1175 utt->command_pid = pid;
1176
1177 if (fr_event_pid_wait(utt, utt->el, &utt->command_ev, pid, _tls_command_exit, utt) < 0) {
1178 PERROR("Failed waiting for the command to exit");
1179 return -1;
1180 }
1181
1182 return 0;
1183}
1184
1185/** Wait for the command started by -e to exit, so its output is complete
1186 *
1187 */
1189{
1190 if (!utt->command_pid || utt->command_exited) return;
1191
1192 utt->command_waiting = true;
1193 (void) fr_event_loop(utt->el);
1194 utt->command_waiting = false;
1195}
1196
1197/** Connect to the server named by -s
1198 *
1199 */
1201{
1202 int fd;
1204
1205 fr_inet_ntop(buffer, sizeof(buffer), &utt->server_ipaddr);
1206
1207 if (utt->conf.socket_type == SOCK_DGRAM) {
1208 fd = fr_socket_client_udp(NULL, NULL, NULL, &utt->server_ipaddr, utt->server_port, false);
1209 } else {
1210 fd = fr_socket_client_tcp(NULL, NULL, &utt->server_ipaddr, utt->server_port, false);
1211 }
1212 if (fd < 0) {
1213 PERROR("Failed connecting to %s port %u", buffer, utt->server_port);
1214 return -1;
1215 }
1216
1217 INFO("Connected to %s port %u on fd %d", buffer, utt->server_port, fd);
1218
1219 utt->fd = fd;
1220
1221 return 0;
1222}
1223
1224/** Build an internal client.
1225 *
1226 * unit_test_tls accepts packets from anywhere (for now), and doesn't read "client" configuration sections.
1227 *
1228 * The client is built by allocating a CONF_SECTION rather than by filling in #fr_client_t manually, which
1229 * allows fields to be examined by `%request.client()`.
1230 *
1231 * "proto = tls" sets both the protocol and tls_required. It also fixes the
1232 * secret at "radsec", so that is the secret set here.
1233 */
1234static fr_client_t *tls_client_alloc(TALLOC_CTX *ctx, fr_ipaddr_t const *ipaddr)
1235{
1236 CONF_SECTION *cs;
1237 fr_client_t *client;
1239
1240 /*
1241 * Written without a prefix, the way a person would write it in
1242 * a "client" section. The "ipaddr" item is a COMBO_IP_PREFIX,
1243 * so a bare host address parses as a /32 or a /128.
1244 */
1245 fr_inet_ntop(buffer, sizeof(buffer), ipaddr);
1246
1247 MEM(cs = cf_section_alloc(ctx, NULL, "client", "unit_test_tls"));
1249 MEM(cf_pair_alloc(cs, "proto", "tls", T_OP_EQ, T_BARE_WORD, T_BARE_WORD));
1250 MEM(cf_pair_alloc(cs, "secret", "radsec", T_OP_EQ, T_BARE_WORD, T_DOUBLE_QUOTED_STRING));
1251 MEM(cf_pair_alloc(cs, "shortname", "unit_test_tls", T_OP_EQ, T_BARE_WORD, T_DOUBLE_QUOTED_STRING));
1252 MEM(cf_pair_alloc(cs, "nas_type", "test", T_OP_EQ, T_BARE_WORD, T_DOUBLE_QUOTED_STRING));
1253
1254 client = client_afrom_cs(ctx, cs, NULL, 0);
1255 if (!client) {
1256 PERROR("Failed creating the client for %s", buffer);
1257 talloc_free(cs);
1258 return NULL;
1259 }
1260
1261 /*
1262 * The client has to outlive the section it was built from,
1263 * because %request.client() reads the section.
1264 */
1265 talloc_steal(client, cs);
1266
1267 return client;
1268}
1269
1270/** Build the request the handshake runs under
1271 *
1272 * The TLS code reads the control list for TLS-Session-Cert-File and
1273 * TLS-Session-Require-Client-Certificate, and writes the negotiated version
1274 * and cipher suite into the session-state list, so a real request is needed.
1275 */
1276static request_t *tls_request_alloc(TALLOC_CTX *ctx, int fd, int socket_type)
1277{
1279 struct sockaddr_storage sa;
1280 socklen_t salen;
1281
1282 static uint64_t number = 0;
1283
1285 if (!request) return NULL;
1286
1287 if (!request->packet) request->packet = fr_packet_alloc(request, false);
1288 if (!request->reply) request->reply = fr_packet_alloc(request, false);
1289
1290 request->packet->timestamp = fr_time();
1291
1292 request->packet->socket.type = socket_type;
1293 request->packet->socket.fd = fd;
1294
1295 salen = sizeof(sa);
1296 if (getpeername(fd, (struct sockaddr *) &sa, &salen) == 0) {
1297 (void) fr_ipaddr_from_sockaddr(&request->packet->socket.inet.src_ipaddr,
1298 &request->packet->socket.inet.src_port, &sa, salen);
1299 request->packet->socket.af = request->packet->socket.inet.src_ipaddr.af;
1300 }
1301
1302 salen = sizeof(sa);
1303 if (getsockname(fd, (struct sockaddr *) &sa, &salen) == 0) {
1304 (void) fr_ipaddr_from_sockaddr(&request->packet->socket.inet.dst_ipaddr,
1305 &request->packet->socket.inet.dst_port, &sa, salen);
1306 }
1307
1308 /*
1309 * The client is the far end of the connection we just accepted.
1310 */
1311 request->client = tls_client_alloc(request, &request->packet->socket.inet.src_ipaddr);
1312 if (!request->client) {
1314 return NULL;
1315 }
1316
1317 request->number = number++;
1318 request->name = talloc_typed_asprintf(request, "%" PRIu64, request->number);
1319 request->master_state = REQUEST_ACTIVE;
1320
1321 request->log.dst = talloc_zero(request, log_dst_t);
1322 request->log.dst->func = vlog_request;
1323 request->log.dst->uctx = &default_log;
1324 request->log.dst->lvl = fr_debug_lvl;
1325
1326 request->log.lvl = fr_debug_lvl;
1327 request->async = talloc_zero(request, fr_async_t);
1328 request->async->request = request;
1329
1330 if (fr_packet_pairs_from_packet(request->request_ctx, &request->request_pairs, request->packet) < 0) {
1331 ERROR("Failed converting connection addresses to attributes");
1333 return NULL;
1334 }
1335
1336 return request;
1337}
1338
1339/** Add the connection to the event loop, and get it moving
1340 *
1341 * Runs from inside the event loop, see tls_connection_run().
1342 */
1344{
1345 unit_test_tls_t *utt = talloc_get_type_abort(uctx, unit_test_tls_t);
1346
1347 /*
1348 * Nothing polls. A handshake round starts when a record arrives,
1349 * and a yielded round resumes when the interpreter marks the
1350 * request runnable.
1351 *
1352 * fr_event_fd_insert() below adds the write event along with the
1353 * socket, and the call to tls_connection_write_wait() then
1354 * suspends the write event, for the reason
1355 * tls_connection_write_wait() gives.
1356 */
1357 if (fr_event_fd_insert(utt, &utt->ef, el, utt->fd,
1359 PERROR("Failed adding the connection to the event loop");
1360 tls_request_failed(utt);
1361 return;
1362 }
1363
1364 /*
1365 * fr_event_fd_insert() added the socket with the write event
1366 * active, which is the state `write_blocked` records, so set
1367 * `write_blocked` to true and then suspend the write event. No
1368 * record is waiting for room yet.
1369 */
1370 utt->write_blocked = true;
1371 if (tls_connection_write_wait(utt, false) < 0) {
1372 tls_request_failed(utt);
1373 return;
1374 }
1375
1376 /*
1377 * Run `new session { ... }` and, for a client, `load session`.
1378 * A server then waits for the ClientHello. A client has to send
1379 * it.
1380 */
1381 fr_tls_connection_wake(utt->conn);
1382}
1383
1384/** Run one connection from the first byte to the last
1385 *
1386 * Everything which belongs to a single connection is allocated here and freed
1387 * again at the end, so that the next connection starts clean. What survives
1388 * is what the cache needs: the interpreter, the modules, and so the sessions
1389 * a policy stored.
1390 */
1392{
1393 int ret = -1;
1394 fr_event_user_t *ev = NULL;
1395 request_t *stale;
1396
1397 utt->connections++;
1398
1399 /*
1400 * A connection of its own for each connection, rather than one
1401 * connection reset by hand between them. Everything the
1402 * library puts on a connection then goes when the connection
1403 * goes, and this program has nothing to remember to clear.
1404 */
1405 TALLOC_FREE(utt->conn);
1406 MEM(utt->conn = fr_tls_connection_alloc(utt, utt->el->tl,
1410 utt->conn->uctx = utt;
1411 utt->conn->client = utt->client;
1412
1413
1414
1415 utt->done = false;
1416 utt->ret = EXIT_SUCCESS;
1417 utt->fd = -1;
1418 utt->ef = NULL;
1419 utt->write_blocked = false;
1420
1421 /*
1422 * Get a connection, one way or the other.
1423 */
1424 if (utt->conn->client) {
1425 if (tls_socket_connect(utt) < 0) return -1;
1426
1427 if (utt->command && !utt->command_pid && (tls_command_start(utt, utt->command) < 0)) return -1;
1428 } else {
1429 if (tls_socket_accept(utt) < 0) return -1;
1430 }
1431
1432 /*
1433 * One place for both roles: the client has just connected,
1434 * and the server has just accepted. Neither socket inherits
1435 * the flag from the listening socket, so both are set here.
1436 */
1437 if (utt->nonblock && (fr_nonblock(utt->fd) < 0)) {
1438 PERROR("Failed setting the connection socket non-blocking");
1439 return -1;
1440 }
1441
1442 utt->conn->request = tls_request_alloc(utt, utt->fd, utt->conf.socket_type);
1443 if (!utt->conn->request) goto finish;
1444
1445 unlang_interpret_set(utt->conn->request, utt->intp);
1446
1447 /*
1448 * Name the connection for the log, now that the socket is known.
1449 * The library gives every connection a name of its own, so the
1450 * old one is freed rather than leaked. Only the application
1451 * knows what identifies a connection, which is why the library
1452 * does not do this itself.
1453 */
1454 {
1455 fr_socket_t *socket = &utt->conn->request->packet->socket;
1456
1457 talloc_const_free(utt->conn->name);
1458 utt->conn->name = fr_asprintf(utt->conn, "%s from %pV:%u to %pV:%u",
1459 (socket->type == SOCK_DGRAM) ? "DTLS" : "TLS",
1460 fr_box_ipaddr(socket->inet.src_ipaddr), socket->inet.src_port,
1461 fr_box_ipaddr(socket->inet.dst_ipaddr), socket->inet.dst_port);
1462 if (!utt->conn->name) goto finish;
1463
1464 DEBUG2("Connection is %s", utt->conn->name);
1465 }
1466
1467 /*
1468 * Both roles run the same handshake driver. Passing the request
1469 * to fr_tls_session_alloc_client() is what gives a client the
1470 * memory BIOs and the certificate validation callback which the
1471 * driver needs, see src/lib/tls/session.c.
1472 */
1473 if (utt->conn->client) {
1474 utt->conn->tls_session = fr_tls_session_alloc_client(utt->conn->request, utt->ssl_ctx, utt->conn->request);
1475 } else {
1476 INFO("Accepted connection from %pV on fd %d",
1477 fr_box_ipaddr(utt->conn->request->packet->socket.inet.src_ipaddr), utt->fd);
1478
1479 utt->conn->tls_session = fr_tls_session_alloc_server(utt->conn->request, utt->ssl_ctx, utt->conn->request,
1481 }
1482
1483 if (!utt->conn->tls_session) {
1484 PERROR("Failed creating the TLS session");
1485 goto finish;
1486 }
1487
1488 /*
1489 * Start the request with a new session, then run the
1490 * interpreter once so that the first frame yields.
1491 * unlang_interpret_mark_runnable() acts only on a
1492 * yielded frame.
1493 */
1494 /*
1495 * Bind the DTLS cookie to the socket this connection runs on.
1496 * The library hashes the whole structure with a key of its own
1497 * and never reads it, and the structure is what the rest of
1498 * the server uses to say which DTLS session a datagram belongs
1499 * to.
1500 */
1501 if (utt->conf.socket_type == SOCK_DGRAM) {
1502 utt->conn->tls_session->cookie = &utt->conn->request->packet->socket;
1503 }
1504
1505 if (fr_tls_connection_push(utt->conn) < 0) {
1506 PERROR("Failed starting new TLS connection");
1507 goto finish;
1508 }
1509
1510 (void) unlang_interpret(utt->conn->request, UNLANG_REQUEST_RESUME);
1511
1512 /*
1513 * A datagram connection starts with a datagram which was read
1514 * from the listening socket, because that is what named the
1515 * peer. The connection's socket never saw it, so hand it over
1516 * now that there is a connection to hand it to.
1517 */
1518 if (utt->first) {
1519 uint8_t *first = utt->first;
1520 size_t first_len = utt->first_len;
1521
1522 utt->first = NULL;
1523 utt->first_len = 0;
1524
1525 DEBUG3("Handing the connection the %zu byte datagram which named the peer", first_len);
1526 fr_tls_connection_recv(utt->conn, first, first_len);
1527 talloc_free(first);
1528 }
1529
1530 if (fr_event_post_insert(utt->el, _tls_runnable, utt) < 0) {
1531 PERROR("Failed adding the runnable handler to the event loop");
1532 goto finish;
1533 }
1534
1535 /*
1536 * The connection is started from inside the event loop rather
1537 * than here. Ending the previous connection left the loop
1538 * flagged as exiting, and fr_event_fd_insert() refuses to add a
1539 * socket to a loop in that state. fr_event_loop() clears the
1540 * flag as it starts, so a user event which fires immediately is
1541 * the first point at which the socket can be added.
1542 */
1543 if (fr_event_user_insert(utt, utt->el, &ev, true, _tls_connection_start, utt) < 0) {
1544 PERROR("Failed scheduling the start of the connection");
1545 goto finish;
1546 }
1547
1548 (void) fr_event_loop(utt->el);
1549
1550 ret = 0;
1551
1552finish:
1553 if (utt->ef) {
1554 (void) fr_event_fd_delete(utt->el, utt->fd, FR_EVENT_FILTER_IO);
1555 utt->ef = NULL;
1556 }
1557 (void) fr_event_post_delete(utt->el, _tls_runnable, utt);
1558
1559 /*
1560 * The user event is allocated in utt, which outlives the event
1561 * list. The destructor of the user event removes it from the
1562 * event list, so free it while the event list still exists.
1563 */
1564 TALLOC_FREE(ev);
1565
1566 /*
1567 * The connection frame is still yielded, so cancel the request to
1568 * unwind the stack before the request is freed.
1569 */
1570 if (utt->conn->request) unlang_interpret_signal(utt->conn->request, FR_SIGNAL_CANCEL);
1571
1572 /*
1573 * Empty the heap before the requests on it are freed. Popping
1574 * clears each entry's index, so nothing is left pointing at
1575 * memory the request pool is about to hand out again.
1576 */
1577 while (fr_heap_pop((void **)&stale, &utt->runnable) == 0) {
1578 if (!stale) break;
1579 }
1580 utt->yielded = 0;
1581
1582 TALLOC_FREE(utt->conn->tls_session);
1583 TALLOC_FREE(utt->conn->request);
1584
1585 if (utt->fd >= 0) {
1586 close(utt->fd);
1587 utt->fd = -1;
1588 }
1589
1590 return ret;
1591}
1592
1593/** Turn a comma separated list of names into the wire format ALPN uses
1594 *
1595 * Each name becomes one length octet followed by the name. There is no
1596 * terminator, so the caller takes the length from the array itself.
1597 *
1598 * @param[in] ctx to allocate in.
1599 * @param[in] names comma separated, in order of preference.
1600 * @return
1601 * - the list, whose talloc array length is the length of the list.
1602 * - NULL if a name is empty or longer than 255 octets.
1603 */
1604static unsigned char *tls_alpn_build(TALLOC_CTX *ctx, char const *names)
1605{
1606 unsigned char *alpn, *p;
1607 char const *q;
1608 size_t len;
1609
1610 /*
1611 * One length octet per name, and the names themselves. The
1612 * separators become those length octets, and the first name has
1613 * no separator before it, so one more octet than the string.
1614 */
1615 MEM(alpn = talloc_zero_array(ctx, unsigned char, strlen(names) + 1));
1616 p = alpn;
1617
1618 for (q = names; *q != '\0'; q += len) {
1619 len = strcspn(q, ",");
1620 if ((len == 0) || (len > 255)) {
1621 ERROR("Each ALPN protocol name must be between 1 and 255 characters");
1622 talloc_free(alpn);
1623 return NULL;
1624 }
1625
1626 *p++ = (unsigned char) len;
1627 memcpy(p, q, len);
1628 p += len;
1629
1630 if (q[len] == ',') len++; /* step over the separator */
1631 }
1632
1633 /*
1634 * A trailing separator, or a repeated one, leaves the array
1635 * longer than what was written into it. Shrink it so the array
1636 * length is the length of the list.
1637 */
1638 MEM(alpn = talloc_realloc(ctx, alpn, unsigned char, (size_t) (p - alpn)));
1639
1640 return alpn;
1641}
1642
1643int main(int argc, char *argv[])
1644{
1645 int ret = EXIT_SUCCESS;
1646 int c;
1647 char const *receipt_file = NULL;
1648 char const *command = NULL;
1649 char const *server = NULL;
1650 unsigned int count = 1;
1651 bool alert = false;
1652 bool invalid = false;
1653 bool nonblock = false;
1654 bool reject = false;
1655 bool app_data = false;
1656 bool hold = false;
1657 bool client = false;
1658 char const *alpn_names = NULL;
1659 bool alpn_required = false;
1660 unsigned int i;
1661
1662 TALLOC_CTX *autofree;
1663 TALLOC_CTX *thread_ctx;
1664
1665 char *p;
1667
1668 fr_dict_t *dict = NULL;
1669 fr_dict_t const *dict_check;
1670
1671 virtual_server_t const *vs;
1672 CONF_SECTION *utt_cs;
1673
1674 unit_test_tls_t *utt = NULL;
1675 fr_tls_conf_t *conf = NULL;
1676
1677 /*
1678 * Must be called first, so the handler is called last
1679 */
1681
1683 thread_ctx = talloc_new(autofree);
1684
1686 if (!config) {
1687 fr_perror("unit_test_tls");
1688 fr_exit_now(EXIT_FAILURE);
1689 }
1690
1691 p = strrchr(argv[0], FR_DIR_SEP);
1692 if (!p) {
1693 main_config_name_set_default(config, argv[0], false);
1694 } else {
1695 main_config_name_set_default(config, p + 1, false);
1696 }
1697
1699
1700 if (fr_fault_setup(autofree, getenv("PANIC_ACTION"), argv[0], PANIC_ACTION_SIGNALS) < 0) {
1701 fr_perror("%s", config->name);
1702 fr_exit_now(EXIT_FAILURE);
1703 }
1704#ifdef NDEBUG
1706#endif
1707
1708 fr_debug_lvl = 0;
1709 fr_time_start();
1710
1711 /*
1712 * The tests should have only IPs, not host names.
1713 */
1715
1716 /*
1717 * We always log to stdout.
1718 */
1720 default_log.fd = STDOUT_FILENO;
1721 default_log.print_level = true;
1722
1723 /* Process the options. */
1724 while ((c = getopt(argc, argv, "ABc:Cd:D:e:hHIlL:Mn:Pr:Rs:xX")) != -1) {
1725 switch (c) {
1726 case 'A':
1727 alert = true;
1728 break;
1729
1730 case 'B':
1731 nonblock = true;
1732 break;
1733
1734 case 'R':
1735 reject = true;
1736 break;
1737
1738 case 'c':
1739 count = (unsigned int) atoi(optarg);
1740 if (!count) {
1741 fprintf(stderr, "Invalid value \"%s\" for -c\n", optarg);
1742 fr_exit_now(EXIT_FAILURE);
1743 }
1744 break;
1745
1746 case 'C':
1747 check_config = true;
1748 break;
1749
1750 case 'd':
1752 break;
1753
1754 case 'D':
1756 break;
1757
1758 case 'h':
1759 usage(config, EXIT_SUCCESS);
1760 break;
1761
1762 case 'I':
1763 invalid = true;
1764 break;
1765
1766 case 'l':
1767 alpn_required = true;
1768 break;
1769
1770 case 'L':
1771 alpn_names = optarg;
1772 break;
1773
1774 case 'M':
1775 talloc_enable_leak_report();
1776 break;
1777
1778 case 'n':
1779 config->name = optarg;
1780 break;
1781
1782 case 'H':
1783 hold = true;
1784 break;
1785
1786 case 'P':
1787 app_data = true;
1788 break;
1789
1790 case 'e':
1791 command = optarg;
1792 break;
1793
1794 case 'r':
1795 receipt_file = optarg;
1796 break;
1797
1798 case 's':
1799 server = optarg;
1800 break;
1801
1802 case 'X':
1803 fr_debug_lvl += 2;
1804 default_log.print_level = true;
1805 break;
1806
1807 case 'x':
1808 fr_debug_lvl++;
1809 if (fr_debug_lvl > 2) default_log.print_level = true;
1810 break;
1811
1812 default:
1813 usage(config, EXIT_FAILURE);
1814 break;
1815 }
1816 }
1817
1818 if (receipt_file && (fr_unlink(receipt_file) < 0)) {
1819 fr_perror("%s", config->name);
1821 }
1822
1823 /*
1824 * A mismatch between the OpenSSL headers used at build time and the
1825 * linked OpenSSL library makes this program exit now, rather than
1826 * crash later.
1827 */
1829
1830 /*
1831 * fr_openssl_init() must be called before *ANY* OpenSSL functions are
1832 * used, which is why
1833 * fr_openssl_init() is called so early.
1834 */
1835 if (fr_openssl_init() < 0) EXIT_WITH_FAILURE;
1836
1838
1839 /*
1840 * Mismatch between the binary and the libraries it links against
1841 */
1843 fr_perror("%s", config->name);
1845 }
1846
1847 /*
1848 * Initialise the dynamic loader infrastructure, which the config
1849 * file parser uses.
1850 */
1851 modules_init(config->lib_dir);
1852
1853 if (!fr_dict_global_ctx_init(NULL, true, config->dict_dir)) {
1854 fr_perror("%s", config->name);
1856 }
1857
1859 fr_perror("%s", config->name);
1861 }
1862
1863 if (fr_tls_dict_init() < 0) EXIT_WITH_FAILURE;
1864
1865 /*
1866 * Load the custom dictionary
1867 */
1868 if (fr_dict_read(dict, config->confdir, FR_DICTIONARY_FILE) == -1) {
1869 PERROR("Failed to initialize the dictionaries");
1871 }
1872
1874 fr_perror("%s", config->name);
1876 }
1877
1878 if (request_global_init() < 0) {
1879 fr_perror("%s", config->name);
1881 }
1882
1883 /*
1884 * The triggers are run-time expansions, so the triggers need the
1885 * main event loop.
1886 */
1887 if (main_loop_init() < 0) {
1888 PERROR("Failed initialising main event loop");
1890 }
1891
1892 if (unlang_global_init() < 0) {
1893 fr_perror("%s", config->name);
1895 }
1896
1897 if (modules_rlm_init() < 0) {
1898 fr_perror("%s", config->name);
1900 }
1901
1902 if (virtual_servers_init() < 0) {
1903 fr_perror("%s", config->name);
1905 }
1906
1908
1909 MEM(utt = talloc_zero(autofree, unit_test_tls_t));
1910 utt->sockfd = utt->fd = -1;
1911 utt->ret = EXIT_SUCCESS;
1912 utt->count = count;
1913 utt->alert = alert;
1914 utt->invalid = invalid;
1915 utt->nonblock = nonblock;
1916 utt->app_data = app_data;
1917 utt->hold = hold;
1918 utt->reject = reject;
1919
1920
1921 /*
1922 * Bootstrap and instantiate the virtual servers and the modules
1923 * that the virtual servers use. The TLS subsections name a
1924 * virtual server, so server_init() has to run before
1925 * cf_section_parse() reads the `unit_test_tls` section.
1926 */
1927 if (server_init(config->root_cs, config->confdir, dict) < 0) EXIT_WITH_FAILURE;
1928
1929 vs = virtual_server_find("tls");
1930 if (!vs) {
1931 ERROR("Cannot find virtual server 'tls'");
1933 }
1934
1935 dict_check = virtual_server_dict_by_name("tls");
1936 if (!dict_check || !fr_dict_compatible(dict_check, dict_tls)) {
1937 ERROR("Virtual server 'tls' must have 'namespace = tls'");
1939 }
1940
1941 /*
1942 * Parse the settings that steer the test program, with the TLS
1943 * configuration for each role as a subsection. The TLS rows
1944 * resolve the `virtual_server` item through
1945 * virtual_server_cf_parse(), so server_init() had to run first.
1946 * cf_section_parse_pass2() then resolves the expansions in the
1947 * TLS subsections.
1948 */
1949 utt_cs = cf_section_find(config->root_cs, "unit_test_tls", NULL);
1950 if (!utt_cs) {
1951 ERROR("Cannot find a top-level 'unit_test_tls { ... }' section in %s.conf", config->name);
1953 }
1954
1956
1957 if ((cf_section_parse(utt, &utt->conf, utt_cs) < 0) ||
1958 (cf_section_parse_pass2(&utt->conf, utt_cs) < 0)) {
1959 cf_log_perr(utt_cs, "Failed parsing the 'unit_test_tls' section");
1961 }
1962
1963 /*
1964 * Resolve `transport` into the socket it names, and into the
1965 * socket type which the TLS configuration below is given.
1966 */
1967 if (strcmp(utt->conf.transport, "tcp") == 0) {
1968 utt->conf.socket_type = SOCK_STREAM;
1969 utt->conf.ipaddr = utt->conf.tcp.ipaddr;
1970 utt->conf.port = utt->conf.tcp.port;
1971
1972 } else if (strcmp(utt->conf.transport, "udp") == 0) {
1973 utt->conf.socket_type = SOCK_DGRAM;
1974 utt->conf.ipaddr = utt->conf.udp.ipaddr;
1975 utt->conf.port = utt->conf.udp.port;
1976
1977 } else {
1978 cf_log_err(utt_cs, "Invalid transport name \"%s\", expected \"tcp\" or \"udp\"",
1979 utt->conf.transport);
1981 }
1982
1983 /*
1984 * -s turns the program around: instead of listening for a
1985 * connection, it makes one.
1986 */
1987 if (server) {
1988 utt->client = client = true;
1989
1990 if (fr_inet_pton_port(&utt->server_ipaddr, &utt->server_port, server,
1991 -1, AF_UNSPEC, true, false) < 0) {
1992 PERROR("Invalid value \"%s\" for -s", server);
1994 }
1995
1996 /*
1997 * fr_inet_pton_port() clears the port before it starts,
1998 * so a missing port is zero here, and not the default.
1999 */
2000 if (!utt->server_port) utt->server_port = utt->conf.port;
2001
2002 if (!utt->server_port) {
2003 ERROR("No port given in -s, and no 'port' in the 'unit_test_tls' section");
2005 }
2006 }
2007
2008 conf = client ? utt->conf.client : utt->conf.server;
2009 if (!conf) {
2010 cf_log_err(utt_cs, "Cannot run as %s, the 'unit_test_tls' section has no '%s { ... }' subsection",
2011 client ? "client" : "server", client ? "client" : "server");
2013 }
2014
2015 /*
2016 * ALPN is not parsed from the configuration file. The library
2017 * leaves the protocol list to the application, so set it here,
2018 * after the TLS configuration is parsed and before the context
2019 * is built from it. See src/lib/tls/alpn.c.
2020 */
2021 if (alpn_names) {
2022 utt->alpn = tls_alpn_build(utt, alpn_names);
2023 if (!utt->alpn) EXIT_WITH_FAILURE;
2024
2025 conf->alpn = utt->alpn;
2026 conf->sizeof_alpn = talloc_array_length(utt->alpn);
2027 }
2028 conf->alpn_required = alpn_required;
2029
2030 /*
2031 * The transport is set by the application for the same reason
2032 * the ALPN strings are: one `tls { ... }` section is parsed by
2033 * the same rules everywhere, and only the application knows
2034 * what it opened the socket as.
2035 */
2036 conf->socket_type = utt->conf.socket_type;
2037
2038 utt->ssl_ctx = fr_tls_ctx_alloc(conf, client);
2039 if (!utt->ssl_ctx) {
2040 cf_log_perr(utt_cs, "Failed creating the TLS context");
2042 }
2043
2044 /*
2045 * The configuration parsed without error, so exit with success.
2046 */
2047 if (check_config) {
2048 DEBUG("Configuration appears to be OK");
2049 goto cleanup;
2050 }
2051
2052 utt->el = main_loop_event_list();
2053 fr_assert(utt->el != NULL);
2054
2055
2057
2058 /*
2059 * Simulate thread-specific instantiation
2060 */
2062 if (fr_thread_instantiate(thread_ctx, utt->el) < 0) {
2063 fr_perror("%s", config->name);
2065 }
2066
2067 if (modules_rlm_coord_attach(utt->el) < 0) {
2068 fr_perror("%s", config->name);
2070 }
2071
2072 if (fr_coord_pre_event_insert(utt->el) < 0) {
2073 fr_strerror_const("Failed adding coordinator pre-check to event list");
2075 }
2076
2077 if (fr_coord_post_event_insert(utt->el) < 0) {
2078 fr_strerror_const("Failed adding coordinator post-check to event list");
2080 }
2081
2082 /*
2083 * Set the panic action (if required)
2084 */
2085 {
2086 char const *panic_action = NULL;
2087
2088 panic_action = getenv("PANIC_ACTION");
2089 if (!panic_action) panic_action = config->panic_action;
2090
2092 fr_perror("%s", config->name);
2094 }
2095 }
2096
2097 setlinebuf(stdout); /* line buffered output */
2098
2099 /*
2100 * One interpreter, one runnable heap and one request for the
2101 * whole connection. The unit_test_tls_t documentation says why.
2102 */
2103 MEM(utt->runnable = fr_heap_talloc_alloc(utt, fr_pointer_cmp, request_t, runnable, 0));
2104
2105 utt->intp = unlang_interpret_init(utt, utt->el,
2107 .init_internal = _request_init_internal,
2108
2109 .done_external = _request_done_external,
2110 .done_internal = _request_done_internal,
2111 .done_detached = _request_done_detached,
2112
2113 .detach = _request_detach,
2114 .yield = _request_yield,
2115 .resume = _request_resume,
2116 .mark_runnable = _request_runnable,
2117 .scheduled = _request_scheduled,
2118 }, utt);
2119 if (!utt->intp) {
2120 fr_perror("%s", config->name);
2122 }
2123
2124 /*
2125 * Subrequests created by the TLS code inherit the thread default,
2126 * so the thread default has to point at the connection's
2127 * interpreter.
2128 */
2130
2131 /*
2132 * A server has one listening socket for every connection it
2133 * accepts, so it is opened once, here.
2134 */
2135 if (!utt->client && (tls_socket_open(utt) < 0)) EXIT_WITH_FAILURE;
2136
2137 /*
2138 * A server starts the command once it is listening. A client
2139 * starts it once the first connection succeeds, see
2140 * tls_connection_run().
2141 */
2142 utt->command = command;
2143 if (!utt->client && command && (tls_command_start(utt, command) < 0)) EXIT_WITH_FAILURE;
2144
2145 for (i = 0; i < utt->count; i++) {
2147
2148 if (utt->ret != EXIT_SUCCESS) break;
2149 }
2150
2151 tls_command_wait(utt);
2152
2153 ret = utt->ret;
2154
2155cleanup:
2156 if (utt) {
2157 /*
2158 * tls_connection_run() cleans up everything which belongs
2159 * to one connection. What is left here is what outlives
2160 * them.
2161 */
2162 if (utt->ssl_ctx) SSL_CTX_free(utt->ssl_ctx);
2163
2164 if (utt->sockfd >= 0) close(utt->sockfd);
2165
2166 /*
2167 * A failure left the client running. The reap below
2168 * signals it if it doesn't exit by itself.
2169 */
2170 if (utt->command_pid && !utt->command_exited) {
2172 (void) fr_event_pid_reap(utt->el, utt->command_pid, NULL, NULL);
2173 }
2174 }
2175
2177
2178 /*
2179 * Detach from coordinators.
2180 */
2181 if (utt && utt->el && (modules_rlm_coord_detach() > 0)) {
2182 if (unlikely(fr_coord_close_event_insert(utt->el) < 0)) {
2183 ERROR("Failed setting up coordinator close events");
2184 }
2185 fr_event_loop(utt->el);
2186 }
2187
2188 /*
2189 * Free thread data
2190 */
2191 talloc_free(thread_ctx);
2192
2194
2196
2197 if (utt && utt->el) fr_event_list_reap_signal(utt->el, fr_time_delta_from_sec(5), SIGKILL);
2198
2200
2202
2203 server_free();
2204
2205 /*
2206 * Virtual servers need to be freed before modules
2207 * as state entries containing data with module-specific
2208 * destructors may exist.
2209 */
2211
2213
2215
2216 fr_tls_dict_free();
2217
2219
2220 if (fr_dict_free(&dict, __FILE__) < 0) {
2221 fr_perror("unit_test_tls - dict");
2222 ret = EXIT_FAILURE;
2223 }
2224
2225 fr_openssl_free();
2226
2227 if (receipt_file && (ret == EXIT_SUCCESS) && (fr_touch(NULL, receipt_file, 0644, true, 0755) <= 0)) {
2228 fr_perror("unit_test_tls");
2229 ret = EXIT_FAILURE;
2230 }
2231
2232 if (talloc_free(autofree) < 0) {
2233 fr_perror("unit_test_tls - autofree");
2234 ret = EXIT_FAILURE;
2235 }
2236
2237 /*
2238 * Ensure our atexit handlers run before any other
2239 * atexit handlers registered by third party libraries.
2240 */
2242
2243 return ret;
2244}
2245
2246/*
2247 * Display the syntax for starting this program.
2248 */
2249static NEVER_RETURNS void usage(main_config_t const *config, int status)
2250{
2251 FILE *output = status ? stderr : stdout;
2252
2253 fprintf(output, "Usage: %s [options]\n", config->name);
2254 fprintf(output, "Options:\n");
2255 fprintf(output, " -A Reject the peer with a fatal TLS alert on the last connection,\n");
2256 fprintf(output, " rather than completing the handshake. With -c 2 the first\n");
2257 fprintf(output, " connection fills the session cache, so the alert then has a\n");
2258 fprintf(output, " session to clear. Used to test the alert and clear paths.\n");
2259 fprintf(output, " -B Put the connection socket in non-blocking mode, so that a read()\n");
2260 fprintf(output, " or a write() which would wait returns EAGAIN instead. The event\n");
2261 fprintf(output, " loop already waits for the socket to be readable or writable, so\n");
2262 fprintf(output, " this exercises the EAGAIN paths rather than changing what runs.\n");
2263 fprintf(output, " -I Mark the session invalid part way through the handshake on the\n");
2264 fprintf(output, " last connection, the way fr_tls_session_msg_cb() marks a record\n");
2265 fprintf(output, " FreeRADIUS refuses. The next round then refuses to continue, and\n");
2266 fprintf(output, " sends the peer a fatal alert saying so.\n");
2267 fprintf(output, " -R Reject the session once the handshake has succeeded on the last\n");
2268 fprintf(output, " connection, as policy would. The cached session is then cleared\n");
2269 fprintf(output, " rather than stored. With -c 2 the first connection fills the\n");
2270 fprintf(output, " cache and the second resumes from it before being rejected, so\n");
2271 fprintf(output, " the clear then has a loaded session to remove.\n");
2272 fprintf(output, " -H Once the connection is up, send nothing and hold it open.\n");
2273 fprintf(output, " A peer which is still owed a session ticket or a byte of\n");
2274 fprintf(output, " application data then waits for something which never\n");
2275 fprintf(output, " arrives, which is what exercises the post-handshake timer.\n");
2276 fprintf(output, " -c <count> Run <count> connections, one after another. Session resumption\n");
2277 fprintf(output, " needs two: one to fill the cache, one to resume from it.\n");
2278 fprintf(output, " -C Check configuration and exit.\n");
2279 fprintf(output, " -d <confdir> Configuration file directory. (defaults to " CONFDIR ").\n");
2280 fprintf(output, " -D <dict_dir> Dictionary files are in \"dict_dir/*\".\n");
2281 fprintf(output, " -e <command> Run <command> in a shell. A server runs it once it is\n");
2282 fprintf(output, " listening, so <command> can be what connects to the server,\n");
2283 fprintf(output, " such as openssl s_client. If <command> exits without\n");
2284 fprintf(output, " connecting, the server fails instead of waiting. With -s,\n");
2285 fprintf(output, " it runs once the first connection succeeds. Either way,\n");
2286 fprintf(output, " unit_test_tls waits for <command> to exit before it exits.\n");
2287 fprintf(output, " -h Print this help message.\n");
2288 fprintf(output, " -M Enable talloc leak reporting.\n");
2289 fprintf(output, " -n <name> Read ${confdir}/name.conf instead of ${confdir}/unit_test_tls.conf.\n");
2290 fprintf(output, " -P Server only. Send one byte of application data, 0x00, once the\n");
2291 fprintf(output, " handshake is done. A server sends every session ticket before\n");
2292 fprintf(output, " its first byte of application data, so this tells a client that\n");
2293 fprintf(output, " no ticket is still on its way.\n");
2294 fprintf(output, " -r <receipt_file> Create <receipt_file> when the program exits successfully.\n");
2295 fprintf(output, " -s <server[:port]> Connect to <server> as a TLS client, instead of listening\n");
2296 fprintf(output, " for a connection. Reads the 'tls client' section. The port\n");
2297 fprintf(output, " defaults to 'port' from the 'unit_test_tls' section.\n");
2298 fprintf(output, " -X Turn on full debugging.\n");
2299 fprintf(output, " -x Turn on additional debugging. (-xx gives more debugging).\n");
2300
2301 fr_exit_now(status);
2302}
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:712
#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:744
#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:621
void fr_coords_destroy(void)
Clean up coordinators in single threaded mode.
Definition coord.c:603
int fr_coord_close_event_insert(fr_event_list_t *el)
Definition coord.c:905
int fr_coord_post_event_insert(fr_event_list_t *el)
Insert instance specific post-event callbacks.
Definition coord.c:861
int fr_coord_pre_event_insert(fr_event_list_t *el)
Insert instance specific pre-event callbacks.
Definition coord.c:836
#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:937
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:934
#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:2519
void unlang_interpret_set_thread_default(unlang_interpret_t *intp)
Set the default interpreter for this thread.
Definition interpret.c:2550
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:2478
void unlang_interpret_signal(request_t *request, fr_signal_t action)
Send a signal (usually stop) to a request.
Definition interpret.c:1789
#define UNLANG_REQUEST_RESUME
Definition interpret.h:48
External functions provided by the owner of the interpret.
Definition interpret.h:116
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:2398
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:2420
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:63
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:614
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:590
"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)
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)
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)