65RCSID(
"$Id: 0ede88e8267d5cdd479c4a9d37acb24be94dabbb $")
67#include <freeradius-devel/server/base.h>
68#include <freeradius-devel/server/module_rlm.h>
70#include <freeradius-devel/io/listen.h>
71#include <freeradius-devel/io/thread.h>
73#include <freeradius-devel/tls/base.h>
74#include <freeradius-devel/tls/dtls.h>
75#include <freeradius-devel/tls/strerror.h>
76#include <freeradius-devel/tls/version.h>
77#include <freeradius-devel/tls/connection.h>
78#include <freeradius-devel/bio/base.h>
79#include <freeradius-devel/bio/fd.h>
80#include <freeradius-devel/bio/tls.h>
81#include <freeradius-devel/util/misc.h>
83#include <freeradius-devel/unlang/base.h>
84#include <freeradius-devel/unlang/function.h>
85#include <freeradius-devel/unlang/interpret.h>
87#include <freeradius-devel/util/socket.h>
89#include <freeradius-devel/protocol/freeradius/freeradius.internal.h>
97#define EXIT_WITH_FAILURE \
111 { .out = &
dict_tls, .proto =
"tls" },
193 .subcs_type =
"fr_tls_conf_t" },
195 .subcs_type =
"fr_tls_conf_t" },
318 RDEBUG3(
"Initialising internal request");
332 RDEBUG3(
"Done external request");
343 RDEBUG3(
"Done internal request");
350 RDEBUG3(
"Done detached request");
402 if (utt->
done)
return;
431 if (utt->
conn) utt->
conn->failed = TLS_CONNECTION_FAIL_APPLICATION;
454 DEBUG2(
"The peer ended the held connection");
460 UNUSED int fd_errno,
void *uctx)
464 DEBUG2(
"The held connection failed");
478 DEBUG2(
"Connection is up and can carry application data");
490 PERROR(
"Failed sending the application data");
495 DEBUG(
"Sent one byte of application data");
510 DEBUG(
"Holding the connection open, sending nothing");
513 PERROR(
"Failed watching the held connection");
565 utt->
conn->tls_session->invalid =
true;
568 if (utt->
alert && utt->
conn->tls_session && utt->
conn->pending &&
572 if (fr_tls_session_alert(utt->
conn->request, utt->
conn->tls_session,
573 SSL3_AL_FATAL, SSL_AD_ACCESS_DENIED) < 0) {
574 ERROR(
"Failed raising the TLS alert");
610 fr_tls_session_is_init_finished(utt->
conn->tls_session)) {
611 INFO(
"%s the session after a successful handshake",
612 utt->
network_fail ?
"Failing, with a network error," :
"Rejecting");
632 TLS_CONNECTION_FAIL_APPLICATION;
647 fr_tls_session_is_init_finished(utt->
conn->tls_session)) {
648 INFO(
"Aborting the connection with cache operations still queued");
654 if (utt->
done)
return;
674 if ((ipaddr.
af == AF_UNSPEC) || !port) {
675 ERROR(
"Both 'ipaddr' and 'port' must be set in the 'unit_test_tls' section "
676 "when listening for a connection");
683 .transport = dgram ?
"udp" :
"tcp",
686 .src_ipaddr = ipaddr,
689 .backlog_is_set =
true,
732 uint8_t buf[FR_TLS_MAX_PACKET_SIZE];
749 if (accepted == 0)
return 0;
752 PERROR(
"Failed accepting the first datagram");
758 PERROR(
"Failed reading the first datagram");
789 if ((slen > (
ssize_t) DTLS1_RT_HEADER_LENGTH) &&
790 (buf[0] == SSL3_RT_HANDSHAKE) &&
791 (buf[3] == 0) && (buf[4] == 0) &&
792 (buf[DTLS1_RT_HEADER_LENGTH] == SSL3_MT_CLIENT_HELLO))
break;
794 DEBUG2(
"Discarding a %zd byte datagram which does not start a connection", slen);
798 MEM(utt->
first = talloc_memdup(utt, buf, (
size_t) slen));
807 if (rcode == 0)
return 0;
810 PERROR(
"Failed accepting connection");
822 PERROR(
"Failed setting the connection socket mode");
875 PERROR(
"Failed adding the listening socket to the event loop");
890 INFO(
"Waiting for a connection");
893 PERROR(
"Failed scheduling the wait for a connection");
907 return utt->
fd_bio ? 0 : -1;
922 INFO(
"Command (PID %ld) exited with status %d", (
long)pid,
WEXITSTATUS(status));
923 }
else if (WIFSIGNALED(status)) {
924 INFO(
"Command (PID %ld) was killed by signal %d", (
long)pid, WTERMSIG(status));
969 if (utt->
fd >= 0) close(utt->
fd);
971 sigprocmask(SIG_SETMASK, &set, NULL);
972 execl(
"/bin/sh",
"sh",
"-c", command, (
char *)NULL);
976 INFO(
"Started command (PID %ld): %s", (
long)pid, command);
981 PERROR(
"Failed waiting for the command to exit");
1076 talloc_steal(client, cs);
1092 struct sockaddr_storage sa;
1095 static uint64_t number = 0;
1105 request->packet->socket.type = socket_type;
1106 request->packet->socket.fd = fd;
1113 if (getpeername(fd, (
struct sockaddr *) &sa, &salen) == 0) {
1115 &
request->packet->socket.inet.src_port, &sa, salen);
1117 request->packet->socket.inet.src_ipaddr = info->
socket.inet.dst_ipaddr;
1118 request->packet->socket.inet.src_port = info->
socket.inet.dst_port;
1123 if (getsockname(fd, (
struct sockaddr *) &sa, &salen) == 0) {
1125 &
request->packet->socket.inet.dst_port, &sa, salen);
1151 ERROR(
"Failed converting connection addresses to attributes");
1170 PERROR(
"Failed starting the TLS connection");
1188 DEBUG3(
"Handing the connection the %zu byte datagram which named the peer", first_len);
1189 fr_tls_connection_recv(utt->
conn, first, first_len);
1214 utt->
ret = EXIT_SUCCESS;
1229 if (!utt->
request)
goto finish;
1236 PERROR(
"Failed creating the TLS bio");
1244 .connected = tls_bio_connected,
1245 .failed = tls_bio_failed,
1257 (socket->
type == SOCK_DGRAM) ?
"DTLS" :
"TLS",
1258 fr_box_ipaddr(socket->inet.src_ipaddr), socket->inet.src_port,
1259 fr_box_ipaddr(socket->inet.dst_ipaddr), socket->inet.dst_port);
1260 if (!utt->
conn->name)
goto finish;
1266 INFO(
"Accepted connection from %pV on fd %d",
1271 PERROR(
"Failed adding the runnable handler to the event loop");
1284 PERROR(
"Failed scheduling the start of the connection");
1309 TALLOC_FREE(utt->
bio);
1310 TALLOC_FREE(utt->
fd_bio);
1323 TALLOC_FREE(utt->
first);
1342 unsigned char *alpn, *p;
1351 MEM(alpn = talloc_zero_array(ctx,
unsigned char, strlen(
names) + 1));
1354 for (q =
names; *q !=
'\0'; q +=
len) {
1355 len = strcspn(q,
",");
1356 if ((
len == 0) || (
len > 255)) {
1357 ERROR(
"Each ALPN protocol name must be between 1 and 255 characters");
1362 *p++ = (
unsigned char)
len;
1366 if (q[
len] ==
',')
len++;
1374 MEM(alpn = talloc_realloc(ctx, alpn,
unsigned char, (
size_t) (p - alpn)));
1381 int ret = EXIT_SUCCESS;
1384 char const *command = NULL;
1385 char const *server = NULL;
1386 unsigned int count = 1;
1388 bool invalid =
false;
1389 bool nonblock =
false;
1390 bool reject =
false;
1391 bool network_fail =
false;
1392 bool abort_pending =
false;
1393 bool app_data =
false;
1394 bool delay_tickets =
false;
1396 bool client =
false;
1397 char const *alpn_names = NULL;
1398 bool alpn_required =
false;
1402 TALLOC_CTX *thread_ctx;
1414 fr_tls_conf_t *
conf = NULL;
1430 p = strrchr(argv[0], FR_DIR_SEP);
1463 while ((c = getopt(argc, argv,
"ABc:Cd:D:e:hHIlL:Mn:NPQr:Rs:TxX")) != -1) {
1474 network_fail =
true;
1482 abort_pending =
true;
1486 count = (
unsigned int) atoi(optarg);
1488 fprintf(stderr,
"Invalid value \"%s\" for -c\n", optarg);
1514 alpn_required =
true;
1518 alpn_names = optarg;
1522 talloc_enable_leak_report();
1538 delay_tickets =
true;
1620 PERROR(
"Failed to initialize the dictionaries");
1639 PERROR(
"Failed initialising main event loop");
1666 if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
1674 utt->
ret = EXIT_SUCCESS;
1696 ERROR(
"Cannot find virtual server 'tls'");
1702 ERROR(
"Virtual server 'tls' must have 'namespace = tls'");
1716 ERROR(
"Cannot find a top-level 'unit_test_tls { ... }' section in %s.conf",
config->name);
1724 cf_log_perr(utt_cs,
"Failed parsing the 'unit_test_tls' section");
1743 cf_log_err(utt_cs,
"Invalid transport name \"%s\", expected \"tcp\" or \"udp\"",
1753 utt->
client = client =
true;
1756 -1, AF_UNSPEC,
true,
false) < 0) {
1757 PERROR(
"Invalid value \"%s\" for -s", server);
1768 ERROR(
"No port given in -s, and no 'port' in the 'unit_test_tls' section");
1774 cf_log_err(utt_cs,
"'drop_datagram' is not supported by unit_test_bio, use unit_test_tls");
1780 cf_log_err(utt_cs,
"Cannot run as %s, the 'unit_test_tls' section has no '%s { ... }' subsection",
1781 client ?
"client" :
"server", client ?
"client" :
"server");
1785 conf->delayed_tickets = delay_tickets;
1798 conf->sizeof_alpn = talloc_array_length(utt->
alpn);
1800 conf->alpn_required = alpn_required;
1812 cf_log_perr(utt_cs,
"Failed creating the TLS context");
1820 DEBUG(
"Configuration appears to be OK");
1879 .init_internal = _request_init_internal,
1881 .done_external = _request_done_external,
1882 .done_internal = _request_done_internal,
1883 .done_detached = _request_done_detached,
1885 .detach = _request_detach,
1886 .yield = _request_yield,
1887 .resume = _request_resume,
1888 .mark_runnable = _request_runnable,
1889 .scheduled = _request_scheduled,
1917 for (i = 0; i < utt->
count; i++) {
1920 if (utt->
ret != EXIT_SUCCESS)
break;
1955 ERROR(
"Failed setting up coordinator close events");
2023 FILE *output = status ? stderr : stdout;
2025 fprintf(output,
"Usage: %s [options]\n",
config->name);
2026 fprintf(output,
"Options:\n");
2027 fprintf(output,
" -A Reject the peer with a fatal TLS alert on the last connection,\n");
2028 fprintf(output,
" rather than completing the handshake. With -c 2 the first\n");
2029 fprintf(output,
" connection fills the session cache, so the alert then has a\n");
2030 fprintf(output,
" session to clear. Used to test the alert and clear paths.\n");
2031 fprintf(output,
" -B Put the connection socket in non-blocking mode, so that a read()\n");
2032 fprintf(output,
" or a write() which would wait returns EAGAIN instead. The event\n");
2033 fprintf(output,
" loop already waits for the socket to be readable or writable, so\n");
2034 fprintf(output,
" this exercises the EAGAIN paths rather than changing what runs.\n");
2035 fprintf(output,
" -I Mark the session invalid part way through the handshake on the\n");
2036 fprintf(output,
" last connection, the way fr_tls_session_msg_cb() marks a record\n");
2037 fprintf(output,
" FreeRADIUS refuses. The next round then refuses to continue, and\n");
2038 fprintf(output,
" sends the peer a fatal alert saying so.\n");
2039 fprintf(output,
" -R Reject the session once the handshake has succeeded on the last\n");
2040 fprintf(output,
" connection, as policy would. The cached session is then cleared\n");
2041 fprintf(output,
" rather than stored. With -c 2 the first connection fills the\n");
2042 fprintf(output,
" cache and the second resumes from it before being rejected, so\n");
2043 fprintf(output,
" the clear then has a loaded session to remove.\n");
2044 fprintf(output,
" -Q Free the connection on the last connection once the handshake\n");
2045 fprintf(output,
" has succeeded, while `store session` is still queued, to\n");
2046 fprintf(output,
" exercise the path that discards queued cache operations.\n");
2047 fprintf(output,
" -N Fail the session with a network error on the last connection,\n");
2048 fprintf(output,
" once the handshake succeeds, to simulate the peer closing the\n");
2049 fprintf(output,
" connection. With -c 2 the second connection loads a session\n");
2050 fprintf(output,
" from the cache. A network error does not clear the loaded\n");
2051 fprintf(output,
" session, and the session stays in the cache.\n");
2052 fprintf(output,
" -H Once the connection is up, send nothing and hold it open.\n");
2053 fprintf(output,
" A peer which is still owed a session ticket or a byte of\n");
2054 fprintf(output,
" application data then waits for something which never\n");
2055 fprintf(output,
" arrives, which is what exercises the post-handshake timer.\n");
2056 fprintf(output,
" -c <count> Run <count> connections, one after another. Session resumption\n");
2057 fprintf(output,
" needs two: one to fill the cache, one to resume from it.\n");
2058 fprintf(output,
" -C Check configuration and exit.\n");
2059 fprintf(output,
" -d <confdir> Configuration file directory. (defaults to " CONFDIR
").\n");
2060 fprintf(output,
" -D <dict_dir> Dictionary files are in \"dict_dir/*\".\n");
2061 fprintf(output,
" -e <command> Run <command> in a shell. A server runs it once it is\n");
2062 fprintf(output,
" listening, so <command> can be what connects to the server,\n");
2063 fprintf(output,
" such as openssl s_client. If <command> exits without\n");
2064 fprintf(output,
" connecting, the server fails instead of waiting. With -s,\n");
2065 fprintf(output,
" it runs once the first connection succeeds. Either way,\n");
2066 fprintf(output,
" unit_test_bio waits for <command> to exit before it exits.\n");
2067 fprintf(output,
" -h Print this help message.\n");
2068 fprintf(output,
" -M Enable talloc leak reporting.\n");
2069 fprintf(output,
" -n <name> Read ${confdir}/name.conf instead of ${confdir}/unit_test_bio.conf.\n");
2070 fprintf(output,
" -P Server only. Send one byte of application data, 0x00, once the\n");
2071 fprintf(output,
" handshake is done. A server sends every session ticket before\n");
2072 fprintf(output,
" its first byte of application data, so this tells a client that\n");
2073 fprintf(output,
" no ticket is still on its way.\n");
2074 fprintf(output,
" -T Delay stateless TLS 1.3 session tickets, as EAP does. The server\n");
2075 fprintf(output,
" sends none in the handshake.\n");
2076 fprintf(output,
" -r <receipt_file> Create <receipt_file> when the program exits successfully.\n");
2077 fprintf(output,
" -s <server[:port]> Connect to <server> as a TLS client, instead of listening\n");
2078 fprintf(output,
" for a connection. Reads the 'tls client' section. The port\n");
2079 fprintf(output,
" defaults to 'port' from the 'unit_test_tls' section.\n");
2080 fprintf(output,
" -X Turn on full debugging.\n");
2081 fprintf(output,
" -x Turn on additional debugging. (-xx gives more debugging).\n");
static int const char char buffer[256]
int fr_atexit_global_setup(void)
Setup the atexit handler, should be called at the start of a program's execution.
int fr_atexit_global_trigger_all(void)
Cause all global free triggers to fire.
#define fr_atexit_thread_trigger_all(...)
static ssize_t fr_bio_write(fr_bio_t *bio, void *packet_ctx, void const *buffer, size_t size)
Write raw data to a bio.
static ssize_t fr_bio_read(fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size)
Read raw data from a bio.
void * uctx
user ctx, caller can manually set it.
fr_tls_connection_t * fr_bio_tls_conn(fr_bio_tls_t *my)
The TLS connection, so the caller can set conn->name
int fr_bio_tls_connect(fr_bio_tls_t *my)
Take the connection through every state which comes before application data.
fr_bio_tls_t * fr_bio_tls_alloc(request_t *request, fr_bio_t *next, SSL_CTX *ssl_ctx, bool client, bool client_cert)
Allocate a TLS bio.
static uint8_t request[4]
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
#define NEVER_RETURNS
Should be placed before the function return type.
int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs)
Parse a configuration section into user-supplied variables.
int cf_section_parse_pass2(void *base, CONF_SECTION *cs)
Fixup xlat expansions and attributes.
#define CONF_PARSER_TERMINATOR
#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
@ CONF_FLAG_OK_MISSING
OK if it's missing.
#define FR_CONF_SUBSECTION_ALLOC(_name, _flags, _struct, _field, _subcs)
conf_parser_t which allocates a struct and populates it from a subsection
#define cf_section_rules_push(_cs, _rule)
#define FR_CONF_OFFSET_SUBSECTION(_name, _flags, _struct, _field, _subcs)
conf_parser_t which populates a sub-struct using a CONF_SECTION
#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
Defines a CONF_PAIR to C data type mapping.
A section grouping multiple CONF_PAIR.
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.
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
#define cf_log_err(_cf, _fmt,...)
#define cf_log_perr(_cf, _fmt,...)
#define cf_section_alloc(_ctx, _parent, _name1, _name2)
int fr_coords_create(TALLOC_CTX *ctx, fr_event_list_t *el)
Start coordinators in single threaded mode.
void fr_coords_destroy(void)
Clean up coordinators in single threaded mode.
int fr_coord_close_event_insert(fr_event_list_t *el)
int fr_coord_post_event_insert(fr_event_list_t *el)
Insert instance specific post-event callbacks.
int fr_coord_pre_event_insert(fr_event_list_t *el)
Insert instance specific pre-event callbacks.
static char panic_action[512]
The command to execute when panicking.
void fr_disable_null_tracking_on_free(TALLOC_CTX *ctx)
Disable the null tracking context when a talloc chunk is freed.
void fr_talloc_fault_setup(void)
Register talloc fault handlers.
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.
#define PANIC_ACTION_SIGNALS
#define fr_exit_now(_x)
Exit without calling atexit() handlers, producing a log message in debug builds.
void dependency_version_print(void)
static NEVER_RETURNS void usage(void)
#define fr_dict_autofree(_to_free)
bool fr_dict_compatible(fr_dict_t const *dict1, fr_dict_t const *dict2)
See if two dictionaries have the same end parent.
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
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.
#define fr_dict_autoload(_to_load)
#define DICT_AUTOLOAD_TERMINATOR
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.
Specifies a dictionary which must be loaded/loadable for the module to function.
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(...)
#define fr_event_pid_reap(...)
#define fr_event_pid_wait(...)
@ FR_EVENT_FILTER_IO
Combined filter for read/write functions/.
#define fr_event_user_insert(_ctx, _el, _ev_p, _trigger, _callback, _uctx)
fr_bio_t * fr_bio_fd_alloc(TALLOC_CTX *ctx, fr_bio_fd_config_t const *cfg, size_t offset)
Allocate a FD bio.
int fr_bio_fd_accept(TALLOC_CTX *ctx, fr_bio_t **out_p, fr_bio_t *bio)
Accept a new connection on a socket.
fr_bio_fd_info_t const * fr_bio_fd_info(fr_bio_t *bio)
Returns a pointer to the bio-specific information.
fr_socket_t socket
as connected socket
fr_bio_fd_type_t type
accept, connected, unconnected, etc.
@ FR_BIO_FD_CONNECTED
connected client sockets (UDP or TCP)
@ FR_BIO_FD_LISTEN
call fr_bio_fd_accept() for each new connection
@ FR_BIO_FD_TRANSPORT_TCP
TCP over IPv4 or IPv6.
@ FR_BIO_FD_TRANSPORT_UDP
UDP over IPv4 or IPv6.
Configuration for sockets.
Run-time status of the socket.
int fr_heap_insert(fr_heap_t **hp, void *data)
Insert a new element into the heap.
int fr_heap_pop(void **out, fr_heap_t **hp)
Remove a node from the heap.
static bool fr_heap_entry_inserted(fr_heap_index_t heap_idx)
Check if an entry is inserted into a heap.
#define fr_heap_talloc_alloc(_ctx, _cmp, _talloc_type, _field, _init)
Creates a heap that verifies elements are of a specific talloc type.
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.
bool fr_hostname_lookups
hostname -> IP lookups?
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)
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.
bool fr_reverse_lookups
IP -> hostname lookups?
#define FR_IPADDR_STRLEN
Like INET6_ADDRSTRLEN but includes space for the textual Zone ID.
rlm_rcode_t unlang_interpret(request_t *request, bool running)
Run the interpreter for a current request.
void unlang_interpret_set(request_t *request, unlang_interpret_t *intp)
Set a specific interpreter for a request.
void unlang_interpret_set_thread_default(unlang_interpret_t *intp)
Set the default interpreter for this thread.
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.
#define UNLANG_REQUEST_RESUME
External functions provided by the owner of the interpret.
el_self ties the lifetime of the event list to the interpreter
void fr_bio_cb_set(fr_bio_t *bio, fr_bio_cb_funcs_t const *cb)
int server_init(CONF_SECTION *cs, char const *conf_dir, fr_dict_t *dict)
Initialize src/lib/server/.
void server_free(void)
Free src/lib/server/.
Describes a host allowed to send packets to the server.
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.
#define RPEDEBUG(fmt,...)
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.
int unlang_global_init(void)
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.
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.
void fr_event_loop_exit(fr_event_list_t *el, int code)
Signal an event loop exit with the specified code.
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.
int fr_event_loop(fr_event_list_t *el)
Run an event loop.
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.
A file descriptor/filter event.
Stores all information relating to an event list.
Callbacks for kevent() user events.
int fr_unlink(char const *filename)
Remove a regular file from the filesystem.
ssize_t fr_touch(int *fd_out, char const *filename, mode_t mode, bool mkdir, mode_t dir_mode)
Create an empty file.
@ L_DST_STDOUT
Log to stdout.
fr_packet_t * fr_packet_alloc(TALLOC_CTX *ctx, bool new_vector)
Allocate a new fr_packet_t.
Minimal data structure to use the new code.
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.
fr_event_list_t * main_loop_event_list(void)
Return the main loop event list.
int main_loop_init(void)
Initialise the main event loop, setting up signal handlers.
void main_loop_free(void)
static const uint8_t * zero
@ 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.
fr_cmp_ret_t fr_pointer_cmp(void const *a, void const *b)
Compares two pointers.
int fr_nonblock(UNUSED int fd)
int fr_blocking(UNUSED int fd)
int modules_rlm_coord_attach(fr_event_list_t *el)
Runs the coord_attach method of all registered backend modules.
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.
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.
static const conf_parser_t config[]
#define WIFEXITED(stat_val)
#define WEXITSTATUS(stat_val)
rlm_rcode_t
Return codes indicating the result of the module call.
int request_global_init(void)
int request_detach(request_t *child)
Unlink a subrequest from its parent.
#define request_local_alloc_internal(_ctx, _args)
Allocate a new internal request outside of the request pool.
@ REQUEST_ACTIVE
Request is active (running or runnable)
void fr_schedule_worker_id_set(int id)
Explicitly set the worker id for the current thread.
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.
void modules_init(char const *lib_dir)
Perform global initialisation for modules.
fr_log_dst_t dst
Log destination.
int fd
File descriptor to write messages to.
bool print_level
sometimes we don't want log levels printed
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
char * talloc_typed_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Call talloc vasprintf, setting the type on the new chunk correctly.
#define talloc_autofree_context
The original function is deprecated, so replace it with our version.
int fr_thread_instantiate(TALLOC_CTX *ctx, fr_event_list_t *el)
Instantiate thread-specific data for modules, virtual servers, xlats, unlang, and TLS.
static const char * names[8]
int fr_time_start(void)
Initialize the local time.
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
int fr_openssl_version_consistent(void)
static char const * receipt_file
static fr_event_list_t * el
static void _request_yield(request_t *request, void *uctx)
static void _request_done_external(request_t *request, UNUSED rlm_rcode_t rcode, UNUSED void *uctx)
fr_heap_t * runnable
Requests the interpreter has marked runnable.
fr_tls_connection_t * conn
The connection of bio.
fr_ipaddr_t server_ipaddr
Server named by -s.
int main(int argc, char *argv[])
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.
char const * transport
"tcp" or "udp", naming the subsection below which holds the socket.
fr_event_list_t * el
Event list everything runs on.
static void _request_resume(request_t *request, UNUSED void *uctx)
static void tls_runnable_insert(unit_test_bio_t *utt, request_t *request)
Schedule a request, once.
static void _tls_socket_accept_start(fr_event_list_t *el, void *uctx)
Start waiting for a connection, from inside the event loop.
static void _tls_connection_start(UNUSED fr_event_list_t *el, void *uctx)
Start the TLS bio, from inside the event loop.
bool invalid
Mark the session invalid mid-handshake, see -I.
static int tls_connection_run(unit_test_bio_t *utt)
Run one connection from the first byte to the last.
static void _request_runnable(request_t *request, void *uctx)
uint32_t drop_datagram
Drop this datagram rather than sending it, counting from one.
bool alert
Reject the peer with a TLS alert, see -A.
static fr_client_t * tls_client_alloc(TALLOC_CTX *ctx, fr_ipaddr_t const *ipaddr)
Build an internal client.
uint16_t port
Port of the listening socket.
static void _request_done_internal(request_t *request, UNUSED rlm_rcode_t rcode, UNUSED void *uctx)
bool abort_pending
Free the connection once the handshake succeeds, while store session is still queued,...
static bool _request_scheduled(request_t const *request, UNUSED void *uctx)
static fr_dict_t const * dict_freeradius
static const conf_parser_t unit_test_bio_config[]
int yielded
How many requests are currently yielded.
static fr_dict_t const * dict_tls
fr_bio_tls_t * bio
The TLS bio of the connection being run.
unsigned char * alpn
Protocol list built by -L, in the wire format fr_tls_conf_t expects.
static request_t * tls_request_alloc(TALLOC_CTX *ctx, fr_bio_t *fd_bio, int socket_type)
Build the request the handshake runs under.
static int tls_command_start(unit_test_bio_t *utt, char const *command)
Start the command named by -e.
static void _request_detach(request_t *request, UNUSED void *uctx)
fr_tls_conf_t * server
The server { ... } subsection.
static const conf_parser_t unit_test_bio_socket_config[]
The socket items, parsed once per transport subsection.
int socket_type
SOCK_STREAM or SOCK_DGRAM, from transport.
unit_test_bio_socket_t udp
The udp { ... } subsection.
fr_bio_t * fd_bio
The fd bio of the connection being run.
bool app_data
Send one byte of application data once the handshake is done, see -P.
static int tls_socket_open(unit_test_bio_t *utt)
Open the listening socket described by the "unit_test_tls" section.
static void _tls_hold_read(UNUSED fr_event_list_t *el, UNUSED int fd, UNUSED int flags, void *uctx)
Something happened on a connection which -H holds open.
static void tls_done(unit_test_bio_t *utt)
Stop the event loop, recording why.
static void tls_bio_connected(fr_bio_t *bio)
The connection is up, and can carry application data.
bool done
Set once the connection has a result.
fr_tls_conf_t * client
The client { ... } subsection, used with -s.
bool command_exited
The command has exited.
unsigned int connections
How many connections have been run so far.
fr_dict_autoload_t unit_test_bio_dict[]
fr_bio_fd_config_t listen_cfg
Config of listen_bio. The bio keeps the pointer.
static void tls_bio_failed(fr_bio_t *bio)
The TLS bio says the connection failed, at any point.
char const * radiusd_version
bool nonblock
Put the connection socket in non-blocking mode, see -B.
fr_ipaddr_t ipaddr
Address of the listening socket.
int sockfd
Listening socket.
bool hold
Once connected, send nothing and stay connected, see -H.
bool client
Act as the client and connect to a server, rather than accept a connection.
bool network_fail
Fail the session with a network error once the handshake succeeds, see -N.
fr_event_fd_t * accept_ef
Read event for sockfd, while waiting in tls_socket_accept().
SSL_CTX * ssl_ctx
Context built from the "tls" section.
static void tls_request_failed(unit_test_bio_t *utt)
Record a failure this program cannot recover from, and stop.
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.
bool alpn_required
Set by -l.
fr_ipaddr_t ipaddr
Address of the listening socket, copied from whichever subsection transport named.
request_t * request
The request the connection runs under.
bool require_client_certificate
Whether the client has to present a certificate.
#define EXIT_WITH_FAILURE
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.
static int tls_socket_connect(unit_test_bio_t *utt)
Connect to the server named by -s.
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.
fr_bio_fd_config_t fd_cfg
Config of fd_bio. The bio keeps the pointer.
pid_t command_pid
Command started by -e, or 0.
static int tls_socket_accept(unit_test_bio_t *utt)
Wait for a connection, or for the command started by -e to exit without connecting.
char const * command
Command to run, see -e.
unit_test_bio_socket_t tcp
The tcp { ... } subsection.
bool command_waiting
Waiting in tls_command_wait().
static int tls_socket_accept_one(unit_test_bio_t *utt)
Accept a connection, if the listening socket has one queued.
int fd
Accepted or connected socket.
fr_bio_t * listen_bio
Listening fd bio.
static void _request_done_detached(request_t *request, UNUSED rlm_rcode_t rcode, UNUSED void *uctx)
static void _tls_hold_error(UNUSED fr_event_list_t *el, UNUSED int fd, UNUSED int flags, UNUSED int fd_errno, void *uctx)
uint16_t server_port
Port from -s, or from the configuration.
unit_test_bio_conf_t conf
Parsed "unit_test_tls" section.
bool reject
Reject the session once the handshake succeeds, see -R.
size_t first_len
Length of first.
uint8_t * first
The datagram which named the peer, read from the listening socket before the connection's socket exis...
unlang_interpret_t * intp
Interpreter for the connection.
static void _request_init_internal(request_t *request, void *uctx)
An internal request created by the interpreter has to run on ours.
fr_event_pid_t const * command_ev
Waits for the command to exit.
bool connected
The connected callback has run.
bool accepting
Waiting in tls_socket_accept().
static void tls_command_wait(unit_test_bio_t *utt)
Wait for the command started by -e to exit, so its output is complete.
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.
uint16_t port
Port of the listening socket, and the default port for -s.
unsigned int count
How many connections to run.
The "unit_test_tls" section.
State of the test program.
#define FR_DICTIONARY_FILE
#define FR_DICTIONARY_INTERNAL_DIR
int af
AF_INET, AF_INET6, or AF_UNIX.
int fd
File descriptor if this is a live socket.
int type
SOCK_STREAM, SOCK_DGRAM, etc.
Holds information necessary for binding or connecting to a socket.
void fr_perror(char const *fmt,...)
Print the current error to stderr with a prefix.
#define fr_strerror_const(_msg)
int fr_check_lib_magic(uint64_t magic)
Check if the application linking to the library has the correct magic number.
#define RADIUSD_VERSION_BUILD(_x)
Create a version string for a utility in the suite of FreeRADIUS utilities.
#define RADIUSD_MAGIC_NUMBER
#define fr_box_ipaddr(_val)
static fr_sbuff_err_t char size_t * len
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)