56RCSID(
"$Id: ac9e3b96ecde1e3405ad102219a7cec5a29fd567 $")
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" },
301 RDEBUG3(
"Initialising internal request");
315 RDEBUG3(
"Done external request");
326 RDEBUG3(
"Done internal request");
333 RDEBUG3(
"Done detached request");
389 if (utt->
done)
return;
393 utt->
ret = conn->failed ? EXIT_FAILURE : EXIT_SUCCESS;
408 DEBUG2(
"Connection is up and can carry application data");
420 if (utt->
app_data && !conn->client) {
421 fr_tls_session_t *tls_session = conn->tls_session;
424 if (fr_tls_session_send(conn->request, tls_session) < 0) {
425 ERROR(
"Failed encrypting the application data");
430 if (fr_tls_connection_write(conn) < 0) {
431 ERROR(
"Failed sending the application data");
436 DEBUG(
"Sent one byte of application data");
449 DEBUG(
"Holding the connection open, sending nothing");
463 utt->
conn->failed = TLS_CONNECTION_FAIL_APPLICATION;
495 PERROR(
"Failed updating the write event for the connection");
533 slen = write(utt->
fd,
data, size);
534 if (slen >= 0)
break;
536 switch (fr_tls_connection_io_error(conn, slen)) {
537 case FR_TLS_CONNECTION_IO_RETRY:
540 case FR_TLS_CONNECTION_IO_BLOCKED:
547 DEBUG3(
"Blocked writing %zu bytes to the connection", size);
552 case FR_TLS_CONNECTION_IO_EOF:
553 ERROR(
"Connection closed by the peer while writing to it");
561 case FR_TLS_CONNECTION_IO_OK:
562 case FR_TLS_CONNECTION_IO_FATAL:
571 ERROR(
"Wrote no data to connection");
582 DEBUG3(
"Wrote %zd bytes to the connection", slen);
602 if (utt->
done)
return;
611 fr_tls_connection_process(utt->
conn);
622 uint8_t buf[SSL3_RT_MAX_PLAIN_LENGTH];
625 if (utt->
done)
return;
627 slen = read(fd, buf,
sizeof(buf));
634 switch (fr_tls_connection_io_error(utt->
conn, slen)) {
641 case FR_TLS_CONNECTION_IO_RETRY:
642 case FR_TLS_CONNECTION_IO_BLOCKED:
643 DEBUG3(
"Blocked reading from the connection");
646 case FR_TLS_CONNECTION_IO_EOF:
647 DEBUG2(
"Peer closed the connection on fd %d, read returned EOF", fd);
655 case FR_TLS_CONNECTION_IO_OK:
656 case FR_TLS_CONNECTION_IO_FATAL:
664 fr_tls_connection_recv(utt->
conn, buf, (
size_t) slen);
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);
688 (void) fr_tls_connection_io_error(utt->
conn, -1);
734 utt->
conn->tls_session->invalid =
true;
737 if (utt->
alert && utt->
conn->tls_session && utt->
conn->pending &&
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");
779 fr_tls_session_is_init_finished(utt->
conn->tls_session)) {
780 INFO(
"Rejecting the session after a successful handshake");
799 utt->
conn->failed = TLS_CONNECTION_FAIL_APPLICATION;
803 if (utt->
done)
return;
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");
845 if (setsockopt(
sockfd, SOL_SOCKET, SO_REUSEPORT, &on,
sizeof(on)) < 0) {
874 PERROR(
"Failed setting the listening socket non-blocking");
912 struct sockaddr_storage peer;
914 uint8_t buf[FR_TLS_MAX_PACKET_SIZE];
929 peerlen =
sizeof(peer);
931 slen = recvfrom(utt->
sockfd, buf,
sizeof(buf), 0, (
struct sockaddr *) &peer, &peerlen);
933 if ((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINTR))
return 0;
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;
974 DEBUG2(
"Discarding a %zd byte datagram which does not start a connection", slen);
979 PERROR(
"Failed opening the connection's datagram socket");
983 if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &on,
sizeof(on)) < 0) {
990 PERROR(
"Failed binding the connection's datagram socket");
995 if (connect(fd, (
struct sockaddr *) &peer, peerlen) < 0) {
1001 MEM(utt->
first = talloc_memdup(utt, buf, (
size_t) slen));
1009 fd = accept(utt->
sockfd, NULL, NULL);
1011 if ((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINTR))
return 0;
1023 PERROR(
"Failed setting the connection socket blocking");
1076 PERROR(
"Failed adding the listening socket to the event loop");
1091 INFO(
"Waiting for a connection");
1094 PERROR(
"Failed scheduling the wait for a connection");
1108 return (utt->
fd < 0) ? -1 : 0;
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));
1166 if (utt->
fd >= 0) close(utt->
fd);
1168 sigprocmask(SIG_SETMASK, &set, NULL);
1169 execl(
"/bin/sh",
"sh",
"-c", command, (
char *)NULL);
1173 INFO(
"Started command (PID %ld): %s", (
long)pid, command);
1178 PERROR(
"Failed waiting for the command to exit");
1265 talloc_steal(client, cs);
1279 struct sockaddr_storage sa;
1282 static uint64_t number = 0;
1292 request->packet->socket.type = socket_type;
1293 request->packet->socket.fd = fd;
1296 if (getpeername(fd, (
struct sockaddr *) &sa, &salen) == 0) {
1298 &
request->packet->socket.inet.src_port, &sa, salen);
1299 request->packet->socket.af =
request->packet->socket.inet.src_ipaddr.af;
1303 if (getsockname(fd, (
struct sockaddr *) &sa, &salen) == 0) {
1305 &
request->packet->socket.inet.dst_port, &sa, salen);
1331 ERROR(
"Failed converting connection addresses to attributes");
1359 PERROR(
"Failed adding the connection to the event loop");
1381 fr_tls_connection_wake(utt->
conn);
1405 TALLOC_FREE(utt->
conn);
1406 MEM(utt->
conn = fr_tls_connection_alloc(utt, utt->
el->tl,
1410 utt->
conn->uctx = utt;
1416 utt->
ret = EXIT_SUCCESS;
1424 if (utt->
conn->client) {
1438 PERROR(
"Failed setting the connection socket non-blocking");
1443 if (!utt->
conn->request)
goto finish;
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;
1473 if (utt->
conn->client) {
1474 utt->
conn->tls_session = fr_tls_session_alloc_client(utt->
conn->request, utt->
ssl_ctx, utt->
conn->request);
1476 INFO(
"Accepted connection from %pV on fd %d",
1479 utt->
conn->tls_session = fr_tls_session_alloc_server(utt->
conn->request, utt->
ssl_ctx, utt->
conn->request,
1483 if (!utt->
conn->tls_session) {
1484 PERROR(
"Failed creating the TLS session");
1502 utt->
conn->tls_session->cookie = &utt->
conn->request->packet->socket;
1505 if (fr_tls_connection_push(utt->
conn) < 0) {
1506 PERROR(
"Failed starting new TLS connection");
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);
1531 PERROR(
"Failed adding the runnable handler to the event loop");
1544 PERROR(
"Failed scheduling the start of the connection");
1582 TALLOC_FREE(utt->
conn->tls_session);
1583 TALLOC_FREE(utt->
conn->request);
1606 unsigned char *alpn, *p;
1615 MEM(alpn = talloc_zero_array(ctx,
unsigned char, strlen(
names) + 1));
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");
1626 *p++ = (
unsigned char)
len;
1630 if (q[
len] ==
',')
len++;
1638 MEM(alpn = talloc_realloc(ctx, alpn,
unsigned char, (
size_t) (p - alpn)));
1645 int ret = EXIT_SUCCESS;
1648 char const *command = NULL;
1649 char const *server = NULL;
1650 unsigned int count = 1;
1652 bool invalid =
false;
1653 bool nonblock =
false;
1654 bool reject =
false;
1655 bool app_data =
false;
1657 bool client =
false;
1658 char const *alpn_names = NULL;
1659 bool alpn_required =
false;
1663 TALLOC_CTX *thread_ctx;
1675 fr_tls_conf_t *
conf = NULL;
1691 p = strrchr(argv[0], FR_DIR_SEP);
1724 while ((c = getopt(argc, argv,
"ABc:Cd:D:e:hHIlL:Mn:Pr:Rs:xX")) != -1) {
1739 count = (
unsigned int) atoi(optarg);
1741 fprintf(stderr,
"Invalid value \"%s\" for -c\n", optarg);
1767 alpn_required =
true;
1771 alpn_names = optarg;
1775 talloc_enable_leak_report();
1869 PERROR(
"Failed to initialize the dictionaries");
1888 PERROR(
"Failed initialising main event loop");
1911 utt->
ret = EXIT_SUCCESS;
1931 ERROR(
"Cannot find virtual server 'tls'");
1937 ERROR(
"Virtual server 'tls' must have 'namespace = tls'");
1951 ERROR(
"Cannot find a top-level 'unit_test_tls { ... }' section in %s.conf",
config->name);
1959 cf_log_perr(utt_cs,
"Failed parsing the 'unit_test_tls' section");
1978 cf_log_err(utt_cs,
"Invalid transport name \"%s\", expected \"tcp\" or \"udp\"",
1988 utt->
client = client =
true;
1991 -1, AF_UNSPEC,
true,
false) < 0) {
1992 PERROR(
"Invalid value \"%s\" for -s", server);
2003 ERROR(
"No port given in -s, and no 'port' in the 'unit_test_tls' section");
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");
2026 conf->sizeof_alpn = talloc_array_length(utt->
alpn);
2028 conf->alpn_required = alpn_required;
2040 cf_log_perr(utt_cs,
"Failed creating the TLS context");
2048 DEBUG(
"Configuration appears to be OK");
2107 .init_internal = _request_init_internal,
2109 .done_external = _request_done_external,
2110 .done_internal = _request_done_internal,
2111 .done_detached = _request_done_detached,
2113 .detach = _request_detach,
2114 .yield = _request_yield,
2115 .resume = _request_resume,
2116 .mark_runnable = _request_runnable,
2117 .scheduled = _request_scheduled,
2145 for (i = 0; i < utt->
count; i++) {
2148 if (utt->
ret != EXIT_SUCCESS)
break;
2183 ERROR(
"Failed setting up coordinator close events");
2251 FILE *output = status ? stderr : stdout;
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");
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.
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)
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.
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)