56RCSID(
"$Id: 918d4fc82532ce7a4786c7ac0d9fe3eae5609f11 $")
58#include <freeradius-devel/server/base.h>
59#include <freeradius-devel/server/module_rlm.h>
61#include <freeradius-devel/io/listen.h>
62#include <freeradius-devel/io/thread.h>
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>
71#include <freeradius-devel/unlang/base.h>
72#include <freeradius-devel/unlang/function.h>
73#include <freeradius-devel/unlang/interpret.h>
75#include <freeradius-devel/util/socket.h>
77#include <freeradius-devel/protocol/freeradius/freeradius.internal.h>
85#define EXIT_WITH_FAILURE \
99 { .out = &
dict_tls, .proto =
"tls" },
181 .subcs_type =
"fr_tls_conf_t" },
183 .subcs_type =
"fr_tls_conf_t" },
306 RDEBUG3(
"Initialising internal request");
320 RDEBUG3(
"Done external request");
331 RDEBUG3(
"Done internal request");
338 RDEBUG3(
"Done detached request");
394 if (utt->
done)
return;
398 utt->
ret = conn->failed ? EXIT_FAILURE : EXIT_SUCCESS;
413 DEBUG2(
"Connection is up and can carry application data");
425 if (utt->
app_data && !conn->client) {
426 fr_tls_session_t *tls_session = conn->tls_session;
429 if (fr_tls_session_send(conn->request, tls_session) < 0) {
430 ERROR(
"Failed encrypting the application data");
435 if (fr_tls_connection_write(conn) < 0) {
436 ERROR(
"Failed sending the application data");
441 DEBUG(
"Sent one byte of application data");
454 DEBUG(
"Holding the connection open, sending nothing");
468 utt->
conn->failed = TLS_CONNECTION_FAIL_APPLICATION;
500 PERROR(
"Failed updating the write event for the connection");
538 slen = write(utt->
fd,
data, size);
539 if (slen >= 0)
break;
541 switch (fr_tls_connection_io_error(conn, slen)) {
542 case FR_TLS_CONNECTION_IO_RETRY:
545 case FR_TLS_CONNECTION_IO_BLOCKED:
552 DEBUG3(
"Blocked writing %zu bytes to the connection", size);
557 case FR_TLS_CONNECTION_IO_EOF:
558 ERROR(
"Connection closed by the peer while writing to it");
566 case FR_TLS_CONNECTION_IO_OK:
567 case FR_TLS_CONNECTION_IO_FATAL:
576 ERROR(
"Wrote no data to connection");
587 DEBUG3(
"Wrote %zd bytes to the connection", slen);
607 if (utt->
done)
return;
616 fr_tls_connection_process(utt->
conn);
627 uint8_t buf[SSL3_RT_MAX_PLAIN_LENGTH];
630 if (utt->
done)
return;
632 slen = read(fd, buf,
sizeof(buf));
639 switch (fr_tls_connection_io_error(utt->
conn, slen)) {
646 case FR_TLS_CONNECTION_IO_RETRY:
647 case FR_TLS_CONNECTION_IO_BLOCKED:
648 DEBUG3(
"Blocked reading from the connection");
651 case FR_TLS_CONNECTION_IO_EOF:
652 DEBUG2(
"Peer closed the connection on fd %d, read returned EOF", fd);
660 case FR_TLS_CONNECTION_IO_OK:
661 case FR_TLS_CONNECTION_IO_FATAL:
669 fr_tls_connection_recv(utt->
conn, buf, (
size_t) slen);
681 DEBUG2(
"Peer closed the connection on fd %d, event loop reported EOF (flags 0x%x)", fd, (
unsigned int)flags);
682 (void) fr_tls_connection_io_error(utt->
conn, 0);
693 (void) fr_tls_connection_io_error(utt->
conn, -1);
739 utt->
conn->tls_session->invalid =
true;
742 if (utt->
alert && utt->
conn->tls_session && utt->
conn->pending &&
746 if (fr_tls_session_alert(utt->
conn->request, utt->
conn->tls_session,
747 SSL3_AL_FATAL, SSL_AD_ACCESS_DENIED) < 0) {
748 ERROR(
"Failed raising the TLS alert");
784 fr_tls_session_is_init_finished(utt->
conn->tls_session)) {
785 INFO(
"%s the session after a successful handshake",
786 utt->
network_fail ?
"Failing, with a network error," :
"Rejecting");
806 TLS_CONNECTION_FAIL_APPLICATION;
821 fr_tls_session_is_init_finished(utt->
conn->tls_session)) {
822 INFO(
"Aborting the connection with cache operations still queued");
828 if (utt->
done)
return;
845 if ((ipaddr.
af == AF_UNSPEC) || !port) {
846 ERROR(
"Both 'ipaddr' and 'port' must be set in the 'unit_test_tls' section "
847 "when listening for a connection");
870 if (setsockopt(
sockfd, SOL_SOCKET, SO_REUSEPORT, &on,
sizeof(on)) < 0) {
899 PERROR(
"Failed setting the listening socket non-blocking");
937 struct sockaddr_storage peer;
939 uint8_t buf[FR_TLS_MAX_PACKET_SIZE];
954 peerlen =
sizeof(peer);
956 slen = recvfrom(utt->
sockfd, buf,
sizeof(buf), 0, (
struct sockaddr *) &peer, &peerlen);
958 if ((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINTR))
return 0;
994 if ((slen > (
ssize_t) DTLS1_RT_HEADER_LENGTH) &&
995 (buf[0] == SSL3_RT_HANDSHAKE) &&
996 (buf[3] == 0) && (buf[4] == 0) &&
997 (buf[DTLS1_RT_HEADER_LENGTH] == SSL3_MT_CLIENT_HELLO))
break;
999 DEBUG2(
"Discarding a %zd byte datagram which does not start a connection", slen);
1004 PERROR(
"Failed opening the connection's datagram socket");
1008 if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &on,
sizeof(on)) < 0) {
1015 PERROR(
"Failed binding the connection's datagram socket");
1020 if (connect(fd, (
struct sockaddr *) &peer, peerlen) < 0) {
1026 MEM(utt->
first = talloc_memdup(utt, buf, (
size_t) slen));
1034 fd = accept(utt->
sockfd, NULL, NULL);
1036 if ((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINTR))
return 0;
1048 PERROR(
"Failed setting the connection socket blocking");
1101 PERROR(
"Failed adding the listening socket to the event loop");
1116 INFO(
"Waiting for a connection");
1119 PERROR(
"Failed scheduling the wait for a connection");
1133 return (utt->
fd < 0) ? -1 : 0;
1148 INFO(
"Command (PID %ld) exited with status %d", (
long)pid,
WEXITSTATUS(status));
1149 }
else if (WIFSIGNALED(status)) {
1150 INFO(
"Command (PID %ld) was killed by signal %d", (
long)pid, WTERMSIG(status));
1191 if (utt->
fd >= 0) close(utt->
fd);
1193 sigprocmask(SIG_SETMASK, &set, NULL);
1194 execl(
"/bin/sh",
"sh",
"-c", command, (
char *)NULL);
1198 INFO(
"Started command (PID %ld): %s", (
long)pid, command);
1203 PERROR(
"Failed waiting for the command to exit");
1290 talloc_steal(client, cs);
1304 struct sockaddr_storage sa;
1307 static uint64_t number = 0;
1317 request->packet->socket.type = socket_type;
1318 request->packet->socket.fd = fd;
1321 if (getpeername(fd, (
struct sockaddr *) &sa, &salen) == 0) {
1323 &
request->packet->socket.inet.src_port, &sa, salen);
1324 request->packet->socket.af =
request->packet->socket.inet.src_ipaddr.af;
1328 if (getsockname(fd, (
struct sockaddr *) &sa, &salen) == 0) {
1330 &
request->packet->socket.inet.dst_port, &sa, salen);
1356 ERROR(
"Failed converting connection addresses to attributes");
1384 PERROR(
"Failed adding the connection to the event loop");
1406 fr_tls_connection_wake(utt->
conn);
1430 TALLOC_FREE(utt->
conn);
1431 MEM(utt->
conn = fr_tls_connection_alloc(utt, utt->
el->tl,
1435 utt->
conn->uctx = utt;
1441 utt->
ret = EXIT_SUCCESS;
1449 if (utt->
conn->client) {
1463 PERROR(
"Failed setting the connection socket non-blocking");
1468 if (!utt->
conn->request)
goto finish;
1484 (socket->
type == SOCK_DGRAM) ?
"DTLS" :
"TLS",
1485 fr_box_ipaddr(socket->inet.src_ipaddr), socket->inet.src_port,
1486 fr_box_ipaddr(socket->inet.dst_ipaddr), socket->inet.dst_port);
1487 if (!utt->
conn->name)
goto finish;
1498 if (utt->
conn->client) {
1499 utt->
conn->tls_session = fr_tls_session_alloc_client(utt->
conn->request, utt->
ssl_ctx, utt->
conn->request);
1501 INFO(
"Accepted connection from %pV on fd %d",
1504 utt->
conn->tls_session = fr_tls_session_alloc_server(utt->
conn->request, utt->
ssl_ctx, utt->
conn->request,
1508 if (!utt->
conn->tls_session) {
1509 PERROR(
"Failed creating the TLS session");
1527 utt->
conn->tls_session->cookie = &utt->
conn->request->packet->socket;
1530 if (fr_tls_connection_push(utt->
conn) < 0) {
1531 PERROR(
"Failed starting new TLS connection");
1550 DEBUG3(
"Handing the connection the %zu byte datagram which named the peer", first_len);
1551 fr_tls_connection_recv(utt->
conn, first, first_len);
1556 PERROR(
"Failed adding the runnable handler to the event loop");
1569 PERROR(
"Failed scheduling the start of the connection");
1607 TALLOC_FREE(utt->
conn->tls_session);
1608 TALLOC_FREE(utt->
conn->request);
1631 unsigned char *alpn, *p;
1640 MEM(alpn = talloc_zero_array(ctx,
unsigned char, strlen(
names) + 1));
1643 for (q =
names; *q !=
'\0'; q +=
len) {
1644 len = strcspn(q,
",");
1645 if ((
len == 0) || (
len > 255)) {
1646 ERROR(
"Each ALPN protocol name must be between 1 and 255 characters");
1651 *p++ = (
unsigned char)
len;
1655 if (q[
len] ==
',')
len++;
1663 MEM(alpn = talloc_realloc(ctx, alpn,
unsigned char, (
size_t) (p - alpn)));
1670 int ret = EXIT_SUCCESS;
1673 char const *command = NULL;
1674 char const *server = NULL;
1675 unsigned int count = 1;
1677 bool invalid =
false;
1678 bool nonblock =
false;
1679 bool reject =
false;
1680 bool network_fail =
false;
1681 bool abort_pending =
false;
1682 bool app_data =
false;
1683 bool delay_tickets =
false;
1685 bool client =
false;
1686 char const *alpn_names = NULL;
1687 bool alpn_required =
false;
1691 TALLOC_CTX *thread_ctx;
1703 fr_tls_conf_t *
conf = NULL;
1719 p = strrchr(argv[0], FR_DIR_SEP);
1752 while ((c = getopt(argc, argv,
"ABc:Cd:D:e:hHIlL:Mn:NPQr:Rs:TxX")) != -1) {
1763 network_fail =
true;
1771 abort_pending =
true;
1775 count = (
unsigned int) atoi(optarg);
1777 fprintf(stderr,
"Invalid value \"%s\" for -c\n", optarg);
1803 alpn_required =
true;
1807 alpn_names = optarg;
1811 talloc_enable_leak_report();
1827 delay_tickets =
true;
1909 PERROR(
"Failed to initialize the dictionaries");
1928 PERROR(
"Failed initialising main event loop");
1951 utt->
ret = EXIT_SUCCESS;
1973 ERROR(
"Cannot find virtual server 'tls'");
1979 ERROR(
"Virtual server 'tls' must have 'namespace = tls'");
1993 ERROR(
"Cannot find a top-level 'unit_test_tls { ... }' section in %s.conf",
config->name);
2001 cf_log_perr(utt_cs,
"Failed parsing the 'unit_test_tls' section");
2020 cf_log_err(utt_cs,
"Invalid transport name \"%s\", expected \"tcp\" or \"udp\"",
2030 utt->
client = client =
true;
2033 -1, AF_UNSPEC,
true,
false) < 0) {
2034 PERROR(
"Invalid value \"%s\" for -s", server);
2045 ERROR(
"No port given in -s, and no 'port' in the 'unit_test_tls' section");
2052 cf_log_err(utt_cs,
"Cannot run as %s, the 'unit_test_tls' section has no '%s { ... }' subsection",
2053 client ?
"client" :
"server", client ?
"client" :
"server");
2057 conf->delayed_tickets = delay_tickets;
2070 conf->sizeof_alpn = talloc_array_length(utt->
alpn);
2072 conf->alpn_required = alpn_required;
2084 cf_log_perr(utt_cs,
"Failed creating the TLS context");
2092 DEBUG(
"Configuration appears to be OK");
2151 .init_internal = _request_init_internal,
2153 .done_external = _request_done_external,
2154 .done_internal = _request_done_internal,
2155 .done_detached = _request_done_detached,
2157 .detach = _request_detach,
2158 .yield = _request_yield,
2159 .resume = _request_resume,
2160 .mark_runnable = _request_runnable,
2161 .scheduled = _request_scheduled,
2189 for (i = 0; i < utt->
count; i++) {
2192 if (utt->
ret != EXIT_SUCCESS)
break;
2227 ERROR(
"Failed setting up coordinator close events");
2295 FILE *output = status ? stderr : stdout;
2297 fprintf(output,
"Usage: %s [options]\n",
config->name);
2298 fprintf(output,
"Options:\n");
2299 fprintf(output,
" -A Reject the peer with a fatal TLS alert on the last connection,\n");
2300 fprintf(output,
" rather than completing the handshake. With -c 2 the first\n");
2301 fprintf(output,
" connection fills the session cache, so the alert then has a\n");
2302 fprintf(output,
" session to clear. Used to test the alert and clear paths.\n");
2303 fprintf(output,
" -B Put the connection socket in non-blocking mode, so that a read()\n");
2304 fprintf(output,
" or a write() which would wait returns EAGAIN instead. The event\n");
2305 fprintf(output,
" loop already waits for the socket to be readable or writable, so\n");
2306 fprintf(output,
" this exercises the EAGAIN paths rather than changing what runs.\n");
2307 fprintf(output,
" -I Mark the session invalid part way through the handshake on the\n");
2308 fprintf(output,
" last connection, the way fr_tls_session_msg_cb() marks a record\n");
2309 fprintf(output,
" FreeRADIUS refuses. The next round then refuses to continue, and\n");
2310 fprintf(output,
" sends the peer a fatal alert saying so.\n");
2311 fprintf(output,
" -R Reject the session once the handshake has succeeded on the last\n");
2312 fprintf(output,
" connection, as policy would. The cached session is then cleared\n");
2313 fprintf(output,
" rather than stored. With -c 2 the first connection fills the\n");
2314 fprintf(output,
" cache and the second resumes from it before being rejected, so\n");
2315 fprintf(output,
" the clear then has a loaded session to remove.\n");
2316 fprintf(output,
" -Q Free the connection on the last connection once the handshake\n");
2317 fprintf(output,
" has succeeded, while `store session` is still queued, to\n");
2318 fprintf(output,
" exercise the path that discards queued cache operations.\n");
2319 fprintf(output,
" -N Fail the session with a network error on the last connection,\n");
2320 fprintf(output,
" once the handshake succeeds, to simulate the peer closing the\n");
2321 fprintf(output,
" connection. With -c 2 the second connection loads a session\n");
2322 fprintf(output,
" from the cache. A network error does not clear the loaded\n");
2323 fprintf(output,
" session, and the session stays in the cache.\n");
2324 fprintf(output,
" -H Once the connection is up, send nothing and hold it open.\n");
2325 fprintf(output,
" A peer which is still owed a session ticket or a byte of\n");
2326 fprintf(output,
" application data then waits for something which never\n");
2327 fprintf(output,
" arrives, which is what exercises the post-handshake timer.\n");
2328 fprintf(output,
" -c <count> Run <count> connections, one after another. Session resumption\n");
2329 fprintf(output,
" needs two: one to fill the cache, one to resume from it.\n");
2330 fprintf(output,
" -C Check configuration and exit.\n");
2331 fprintf(output,
" -d <confdir> Configuration file directory. (defaults to " CONFDIR
").\n");
2332 fprintf(output,
" -D <dict_dir> Dictionary files are in \"dict_dir/*\".\n");
2333 fprintf(output,
" -e <command> Run <command> in a shell. A server runs it once it is\n");
2334 fprintf(output,
" listening, so <command> can be what connects to the server,\n");
2335 fprintf(output,
" such as openssl s_client. If <command> exits without\n");
2336 fprintf(output,
" connecting, the server fails instead of waiting. With -s,\n");
2337 fprintf(output,
" it runs once the first connection succeeds. Either way,\n");
2338 fprintf(output,
" unit_test_tls waits for <command> to exit before it exits.\n");
2339 fprintf(output,
" -h Print this help message.\n");
2340 fprintf(output,
" -M Enable talloc leak reporting.\n");
2341 fprintf(output,
" -n <name> Read ${confdir}/name.conf instead of ${confdir}/unit_test_tls.conf.\n");
2342 fprintf(output,
" -P Server only. Send one byte of application data, 0x00, once the\n");
2343 fprintf(output,
" handshake is done. A server sends every session ticket before\n");
2344 fprintf(output,
" its first byte of application data, so this tells a client that\n");
2345 fprintf(output,
" no ticket is still on its way.\n");
2346 fprintf(output,
" -r <receipt_file> Create <receipt_file> when the program exits successfully.\n");
2347 fprintf(output,
" -T Delay stateless TLS 1.3 session tickets, as EAP does. The server\n");
2348 fprintf(output,
" sends none in the handshake.\n");
2349 fprintf(output,
" -s <server[:port]> Connect to <server> as a TLS client, instead of listening\n");
2350 fprintf(output,
" for a connection. Reads the 'tls client' section. The port\n");
2351 fprintf(output,
" defaults to 'port' from the 'unit_test_tls' section.\n");
2352 fprintf(output,
" -X Turn on full debugging.\n");
2353 fprintf(output,
" -x Turn on additional debugging. (-xx gives more debugging).\n");
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 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.
#define fr_dbuff_in_bytes(_dbuff_or_marker,...)
Copy a byte sequence into a dbuff or marker.
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_filter_update(...)
#define fr_event_pid_reap(...)
#define FR_EVENT_RESUME(_s, _f)
Re-add the filter for a func from kevent.
#define FR_EVENT_SUSPEND(_s, _f)
Temporarily remove the filter for a func from kevent.
#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)
Callbacks for the FR_EVENT_FILTER_IO filter.
Structure describing a modification to a filter's state.
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.
void unlang_interpret_signal(request_t *request, fr_signal_t action)
Send a signal (usually stop) to a request.
#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
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)
@ 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_SIGNAL_CANCEL
Request has been cancelled.
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.
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.
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.
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.
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.
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.
static int talloc_const_free(void const *ptr)
Free const'd memory.
#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)
uint8_t * first
The datagram which named the peer, read from the listening socket before the connection's socket exis...
unit_test_tls_socket_t udp
The udp { ... } subsection.
static int tls_socket_accept(unit_test_tls_t *utt)
Wait for a connection, or for the command started by -e to exit without connecting.
unsigned int count
How many connections to run.
unit_test_tls_socket_t tcp
The tcp { ... } subsection.
static void _request_done_external(request_t *request, UNUSED rlm_rcode_t rcode, UNUSED void *uctx)
int main(int argc, char *argv[])
static void tls_command_wait(unit_test_tls_t *utt)
Wait for the command started by -e to exit, so its output is complete.
static void _tls_runnable(UNUSED fr_event_list_t *el, UNUSED fr_time_t now, void *uctx)
Drain the runnable heap once per pass of the event loop.
unit_test_tls_conf_t conf
Parsed "unit_test_tls" section.
static void _request_resume(request_t *request, UNUSED void *uctx)
static void _tls_socket_accept_start(fr_event_list_t *el, void *uctx)
Start waiting for a connection, from inside the event loop.
SSL_CTX * ssl_ctx
Context built from the "tls" section.
bool alert
Reject the peer with a TLS alert, see -A.
uint16_t port
Port of the listening socket, and the default port for -s.
static void _request_runnable(request_t *request, void *uctx)
bool abort_pending
Free the connection once the handshake succeeds, while store session is still queued,...
static fr_client_t * tls_client_alloc(TALLOC_CTX *ctx, fr_ipaddr_t const *ipaddr)
Build an internal client.
static int tls_connection_write_wait(unit_test_tls_t *utt, bool wait)
Start or stop waiting for the socket to have room for more records.
static void _request_done_internal(request_t *request, UNUSED rlm_rcode_t rcode, UNUSED void *uctx)
int fd
Accepted or connected socket.
fr_event_list_t * el
Event list everything runs on.
fr_event_fd_t * accept_ef
Read event for sockfd, while waiting in tls_socket_accept().
bool accepting
Waiting in tls_socket_accept().
static void _tls_connection_error(UNUSED fr_event_list_t *el, int fd, int flags, int fd_errno, void *uctx)
The connection failed at the socket level.
static bool _request_scheduled(request_t const *request, UNUSED void *uctx)
bool network_fail
Fail the session with a network error once the handshake succeeds, see -N.
static void _tls_connection_read(UNUSED fr_event_list_t *el, int fd, UNUSED int flags, void *uctx)
A record arrived on the connection, so hand the record to the connection.
static fr_dict_t const * dict_freeradius
static fr_dict_t const * dict_tls
static void tls_request_close(fr_tls_connection_t *conn)
Stop the event loop, recording why.
static void tls_request_failed(unit_test_tls_t *utt)
Record a failure this program cannot recover from, and stop.
bool invalid
Mark the session invalid mid-handshake, see -I.
bool command_waiting
Waiting in tls_command_wait().
char const * command
Command to run, see -e.
static void tls_runnable_insert(unit_test_tls_t *utt, request_t *request)
Schedule a request, once.
static void _request_detach(request_t *request, UNUSED void *uctx)
fr_ipaddr_t ipaddr
Address of the listening socket.
int yielded
How many requests are currently yielded.
uint16_t port
Port of the listening socket.
bool hold
Once connected, send nothing and stay connected, see -H.
static fr_event_update_t const resume_write[]
fr_tls_connection_t * conn
State of the connection being run.
static int tls_command_start(unit_test_tls_t *utt, char const *command)
Start the command named by -e.
bool command_exited
The command has exited.
static void _tls_connection_start(fr_event_list_t *el, void *uctx)
Add the connection to the event loop, and get it moving.
static request_t * tls_request_alloc(TALLOC_CTX *ctx, int fd, int socket_type)
Build the request the handshake runs under.
bool require_client_certificate
Whether the client has to present a certificate.
fr_ipaddr_t ipaddr
Address of the listening socket, copied from whichever subsection transport named.
fr_tls_conf_t * client
The client { ... } subsection, used with -s.
bool app_data
Send one byte of application data once the handshake is done, see -P.
fr_ipaddr_t server_ipaddr
Server named by -s.
static int tls_socket_connect(unit_test_tls_t *utt)
Connect to the server named by -s.
fr_dict_autoload_t unit_test_tls_dict[]
bool reject
Reject the session once the handshake succeeds, see -R.
static void tls_request_connected(fr_tls_connection_t *conn)
The connection is up, and can carry application data.
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
#define FR_DICTIONARY_INTERNAL_DIR
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)