The FreeRADIUS server $Id: a4e7f8c94e8038b7627bcf52356b7ed15955c1d7 $
Loading...
Searching...
No Matches
session.c
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: 29ead16502c3b4b74c540bf2bf3aa371771d8121 $
19 *
20 * @file tls/session.c
21 * @brief Initialise OpenSSL sessions, and read/write data to/from them.
22 *
23 * @copyright 2026 Network RADIUS SAS (legal@networkradius.com)
24 */
25#ifdef WITH_TLS
26#define LOG_PREFIX "tls"
27#define _TLS_PRIVATE 1
28
29#include <freeradius-devel/server/pair.h>
30#include <freeradius-devel/server/log.h>
31
32#include <freeradius-devel/util/debug.h>
33#include <freeradius-devel/util/math.h>
34#include <freeradius-devel/util/base16.h>
35#include <freeradius-devel/util/skip.h>
36#include <freeradius-devel/util/pair_legacy.h>
37
38#include <freeradius-devel/protocol/freeradius/freeradius.internal.h>
39
40#include <freeradius-devel/unlang/action.h>
41#include <freeradius-devel/unlang/call.h>
42#include <freeradius-devel/unlang/interpret.h>
43#include <freeradius-devel/unlang/subrequest.h>
44
45#include <sys/stat.h>
46#include <fcntl.h>
47
48#include <freeradius-devel/protocol/tls/freeradius.h>
49
50#include "attrs.h"
51#include "base.h"
52#include "dtls.h"
53#include "log.h"
54
55#include <openssl/x509v3.h>
56#include <openssl/ssl.h>
57
58static char const *tls_version_str[] = {
59 [SSL2_VERSION] = "SSL 2.0",
60 [SSL3_VERSION] = "SSL 3.0",
61 [TLS1_VERSION] = "TLS 1.0",
62 [TLS1_1_VERSION] = "TLS 1.1",
63 [TLS1_2_VERSION] = "TLS 1.2",
64 [TLS1_3_VERSION] = "TLS 1.3",
65#ifdef TLS1_4_VERSION
66 [TLS1_4_VERSION] = "TLS 1.4",
67#endif
68};
69
70static char const *tls_content_type_str[] = {
71 [SSL3_RT_CHANGE_CIPHER_SPEC] = "change_cipher_spec",
72 [SSL3_RT_ALERT] = "alert",
73 [SSL3_RT_HANDSHAKE] = "handshake",
74 [SSL3_RT_APPLICATION_DATA] = "application_data",
75#ifdef SSL3_RT_HEADER
76 [SSL3_RT_HEADER] = "header",
77#endif
78#ifdef SSL3_RT_INNER_CONTENT_TYPE
79 [SSL3_RT_INNER_CONTENT_TYPE] = "inner_content_type",
80#endif
81};
82
83static char const *tls_alert_description_str[] = {
84 [SSL3_AD_CLOSE_NOTIFY] = "close_notify",
85 [SSL3_AD_UNEXPECTED_MESSAGE] = "unexpected_message",
86 [SSL3_AD_BAD_RECORD_MAC] = "bad_record_mac",
87 [TLS1_AD_DECRYPTION_FAILED] = "decryption_failed",
88 [TLS1_AD_RECORD_OVERFLOW] = "record_overflow",
89 [SSL3_AD_DECOMPRESSION_FAILURE] = "decompression_failure",
90 [SSL3_AD_HANDSHAKE_FAILURE] = "handshake_failure",
91 [SSL3_AD_BAD_CERTIFICATE] = "bad_certificate",
92 [SSL3_AD_UNSUPPORTED_CERTIFICATE] = "unsupported_certificate",
93 [SSL3_AD_CERTIFICATE_REVOKED] = "certificate_revoked",
94 [SSL3_AD_CERTIFICATE_EXPIRED] = "certificate_expired",
95 [SSL3_AD_CERTIFICATE_UNKNOWN] = "certificate_unknown",
96 [SSL3_AD_ILLEGAL_PARAMETER] = "illegal_parameter",
97 [TLS1_AD_UNKNOWN_CA] = "unknown_ca",
98 [TLS1_AD_ACCESS_DENIED] = "access_denied",
99 [TLS1_AD_DECODE_ERROR] = "decode_error",
100 [TLS1_AD_DECRYPT_ERROR] = "decrypt_error",
101 [TLS1_AD_EXPORT_RESTRICTION] = "export_restriction",
102 [TLS1_AD_PROTOCOL_VERSION] = "protocol_version",
103 [TLS1_AD_INSUFFICIENT_SECURITY] = "insufficient_security",
104 [TLS1_AD_INTERNAL_ERROR] = "internal_error",
105 [TLS1_AD_USER_CANCELLED] = "user_cancelled",
106 [TLS1_AD_NO_RENEGOTIATION] = "no_renegotiation",
107#ifdef TLS13_AD_MISSING_EXTENSION
108 [TLS13_AD_MISSING_EXTENSION] = "missing_extension",
109#endif
110#ifdef TLS13_AD_CERTIFICATE_REQUIRED
111 [TLS13_AD_CERTIFICATE_REQUIRED] = "certificate_required",
112#endif
113#ifdef TLS1_AD_UNSUPPORTED_EXTENSION
114 [TLS1_AD_UNSUPPORTED_EXTENSION] = "unsupported_extension",
115#endif
116#ifdef TLS1_AD_CERTIFICATE_UNOBTAINABLE
117 [TLS1_AD_CERTIFICATE_UNOBTAINABLE] = "certificate_unobtainable",
118#endif
119#ifdef TLS1_AD_UNRECOGNIZED_NAME
120 [TLS1_AD_UNRECOGNIZED_NAME] = "unrecognised_name",
121#endif
122#ifdef TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE
123 [TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE] = "bad_certificate_status_response",
124#endif
125#ifdef TLS1_AD_BAD_CERTIFICATE_HASH_VALUE
126 [TLS1_AD_BAD_CERTIFICATE_HASH_VALUE] = "bad_certificate_hash_value",
127#endif
128#ifdef TLS1_AD_UNKNOWN_PSK_IDENTITY
129 [TLS1_AD_UNKNOWN_PSK_IDENTITY] = "unknown_psk_identity",
130#endif
131#ifdef TLS1_AD_NO_APPLICATION_PROTOCOL
132 [TLS1_AD_NO_APPLICATION_PROTOCOL] = "no_application_protocol",
133#endif
134};
135
136static char const *tls_handshake_type_str[] = {
137 [SSL3_MT_HELLO_REQUEST] = "hello_request",
138 [SSL3_MT_CLIENT_HELLO] = "client_hello",
139 [SSL3_MT_SERVER_HELLO] = "server_hello",
140#ifdef SSL3_MT_NEWSESSION_TICKET
141 [SSL3_MT_NEWSESSION_TICKET] = "new_session_ticket",
142#endif
143#ifdef SSL3_MT_END_OF_EARLY_DATA
144 [SSL3_MT_END_OF_EARLY_DATA] = "end_of_early_data",
145#endif
146#ifdef SSL3_MT_ENCRYPTED_EXTENSIONS
147 [SSL3_MT_ENCRYPTED_EXTENSIONS] = "encrypted_extensions",
148#endif
149 [SSL3_MT_CERTIFICATE] = "certificate",
150 [SSL3_MT_SERVER_KEY_EXCHANGE] = "server_key_exchange",
151 [SSL3_MT_CERTIFICATE_REQUEST] = "certificate_request",
152 [SSL3_MT_SERVER_DONE] = "server_hello_done",
153 [SSL3_MT_CERTIFICATE_VERIFY] = "certificate_verify",
154 [SSL3_MT_CLIENT_KEY_EXCHANGE] = "client_key_exchange",
155 [SSL3_MT_FINISHED] = "finished",
156#ifdef SSL3_MT_CERTIFICATE_URL
157 [SSL3_MT_CERTIFICATE_URL] = "certificate_url",
158#endif
159#ifdef SSL3_MT_CERTIFICATE_STATUS
160 [SSL3_MT_CERTIFICATE_STATUS] = "certificate_status",
161#endif
162#ifdef SSL3_MT_SUPPLEMENTAL_DATA
163 [SSL3_MT_SUPPLEMENTAL_DATA] = "supplemental_data",
164#endif
165#ifdef SSL3_MT_KEY_UPDATE
166 [SSL3_MT_KEY_UPDATE] = "key_update",
167#endif
168#ifdef SSL3_MT_NEXT_PROTO
169 [SSL3_MT_NEXT_PROTO] = "next_proto",
170#endif
171#ifdef SSL3_MT_MESSAGE_HASH
172 [SSL3_MT_MESSAGE_HASH] = "message_hash",
173#endif
174#ifdef DTLS1_MT_HELLO_VERIFY_REQUEST
175 [DTLS1_MT_HELLO_VERIFY_REQUEST] = "hello_verify_request",
176#endif
177#ifdef SSL3_MT_CHANGE_CIPHER_SPEC
178 [SSL3_MT_CHANGE_CIPHER_SPEC] = "change_cipher_spec",
179#endif
180};
181
182/** Return the static private key password we have configured
183 *
184 * @param[out] buf Where to write the password to.
185 * @param[in] size The length of buf.
186 * @param[in] rwflag
187 * - 0 if password used for decryption.
188 * - 1 if password used for encryption.
189 * @param[in] u The static password.
190 * @return
191 * - 0 on error.
192 * - >0 on success (the length of the password).
193 */
194int fr_tls_session_password_cb(char *buf, int size, int rwflag UNUSED, void *u)
195{
196 size_t len;
197
198 /*
199 * We do this instead of not registering the callback
200 * to ensure OpenSSL doesn't try and read a password
201 * from stdin (causes server to block).
202 */
203 if (!u) {
204 ERROR("Private key encrypted but no private_key_password configured");
205 return 0;
206 }
207
208 len = strlcpy(buf, (char *)u, size);
209 if (len >= (size_t)size) {
210 ERROR("Password too long. Maximum length is %i bytes", size - 1);
211 return 0;
212 }
213
214 return len;
215}
216
217#ifdef PSK_MAX_IDENTITY_LEN
218/** Verify the PSK identity contains no reserved chars
219 *
220 * @param identity to check.
221 * @return
222 * - true identity does not contain reserved chars.
223 * - false identity contains reserved chars.
224 */
225static bool session_psk_identity_is_safe(const char *identity)
226{
227 char c;
228
229 if (!identity) return true;
230
231 while ((c = *(identity++)) != '\0') {
232 if (isalpha((uint8_t) c) || isdigit((uint8_t) c) || isspace((uint8_t) c) ||
233 (c == '@') || (c == '-') || (c == '_') || (c == '.')) {
234 continue;
235 }
236
237 return false;
238 }
239
240 return true;
241}
242
243/** Determine the PSK to use for an outgoing connection
244 *
245 * @param[in] ssl session.
246 * @param[in] identity The identity of the PSK to search for.
247 * @param[out] psk Where to write the PSK we found (if any).
248 * @param[in] max_psk_len The length of the buffer provided for PSK.
249 * @return
250 * - 0 if no PSK matching identity was found.
251 * - >0 if a PSK matching identity was found (the length of bytes written to psk).
252 */
253unsigned int fr_tls_session_psk_client_cb(SSL *ssl, UNUSED char const *hint,
254 char *identity, unsigned int max_identity_len,
255 unsigned char *psk, unsigned int max_psk_len)
256{
257 unsigned int psk_len;
258 fr_tls_conf_t *conf;
259
260 conf = (fr_tls_conf_t *)SSL_get_ex_data(ssl, FR_TLS_EX_INDEX_CONF);
261 if (!conf) return 0;
262
263 psk_len = talloc_array_length(conf->psk.key);
264 if (psk_len > max_psk_len) return 0;
265
266 strlcpy(identity, conf->psk.identity, max_identity_len);
267 memcpy(psk, conf->psk.key, psk_len);
268
269 return psk_len;
270}
271
272/** Forget the result of `load psk`, so that the next handshake starts with no pending call
273 *
274 * @param[in] tls_session The TLS session that the section ran for.
275 */
276static void tls_session_psk_reset(fr_tls_session_t *tls_session)
277{
278 TALLOC_FREE(tls_session->psk.key);
279 tls_session->psk.key_len = 0;
280 tls_session->psk.state = FR_TLS_PSK_INIT;
281}
282
283/** Determine the PSK to use for an incoming connection
284 *
285 * When the virtual server has a `load psk` section, the callback pauses
286 * the handshake. tls_session_async_handshake_cont() then pushes the
287 * section with fr_tls_session_psk_pending_push(). Once the section has
288 * finished, the callback returns the key that the section placed in
289 * `reply.TLS-PSK-Key`.
290 *
291 * @param[in] ssl session.
292 * @param[in] identity The identity of the PSK to search for.
293 * @param[out] psk Where to write the PSK we found (if any).
294 * @param[in] max_psk_len The length of the buffer provided for PSK.
295 * @return
296 * - 0 if no PSK matching identity was found.
297 * - >0 if a PSK matching identity was found (the length of bytes written to psk).
298 */
299unsigned int fr_tls_session_psk_server_cb(SSL *ssl, const char *identity,
300 unsigned char *psk, unsigned int max_psk_len)
301{
302 size_t psk_len = 0;
303 fr_tls_conf_t *conf;
305
306 conf = (fr_tls_conf_t *)SSL_get_ex_data(ssl, FR_TLS_EX_INDEX_CONF);
307 if (!conf) return 0;
308
309 request = fr_tls_session_request(ssl);
310 if (request && conf->load_psk) {
311 fr_tls_session_t *tls_session = fr_tls_session(ssl);
312 fr_pair_t *vp;
313
314 /*
315 * The passed identity is weird. Deny it.
316 */
317 if (!session_psk_identity_is_safe(identity)) {
318 RWDEBUG("(TLS) Invalid characters in PSK identity %s", identity);
319 fr_tls_session_error_add(request, FR_ERROR_VALUE_PSK_IDENTITY_INVALID);
320 return 0;
321 }
322
323 /*
324 * The `TLS-PSK-Identity` pair stays in the request after the handshake,
325 * so that policies can read the identity. fr_tls_session_psk_pending_push()
326 * copies the pair into the `load psk` subrequest.
327 */
329 if (fr_pair_value_from_str(vp, identity, strlen(identity), NULL, true) < 0) {
330 RPWDEBUG2("Failed parsing TLS PSK Identity");
332 return 0;
333 }
334
335 /*
336 * OpenSSL runs the handshake, including the PSK callback, on a fibre whose
337 * stack OpenSSL sizes. The unlang interpreter never runs on that stack, so
338 * the section runs on the request's own stack:
339 *
340 * 1. The callback records that `load psk` needs to run, and pauses the
341 * handshake.
342 * 2. Control returns to tls_session_async_handshake_cont(), which pushes the
343 * section with fr_tls_session_psk_pending_push().
344 * 3. Once the section has finished, tls_session_async_handshake_cont() resumes
345 * the handshake.
346 * 4. Execution continues after the ASYNC_pause_job() call below.
347 *
348 * The `verify certificate` and session cache sections pause the handshake the
349 * same way.
350 */
351 if (!fr_cond_assert_msg(tls_session->can_pause,
352 "Unexpected call to %s. tls_session_async_handshake_cont must be in call stack",
353 __FUNCTION__)) return 0;
354
355 fr_assert(tls_session->psk.state == FR_TLS_PSK_INIT);
356 tls_session->psk.state = FR_TLS_PSK_REQUESTED;
357 TLS_PENDING_SET(tls_session, FR_TLS_PENDING_PSK);
358 tls_session->psk.max_psk_len = max_psk_len;
359
360 ASYNC_pause_job();
361
362 /*
363 * If the request was cancelled while the handshake was paused,
364 * the section may not have run.
365 */
367 tls_session_psk_reset(tls_session);
368 return 0;
369 }
370
371 switch (tls_session->psk.state) {
372 case FR_TLS_PSK_SUCCESS:
373 break;
374
375 case FR_TLS_PSK_FAILED:
376 tls_session_psk_reset(tls_session);
377 return 0;
378
379 case FR_TLS_PSK_INIT:
380 case FR_TLS_PSK_REQUESTED:
381 fr_assert_msg(0, "Handshake resumed with `load psk` in state %u",
382 tls_session->psk.state);
383 tls_session_psk_reset(tls_session);
384 return 0;
385 }
386
387 /*
388 * _tls_session_psk_load_resume() checked the key, so the
389 * callback only copies the key into the `psk` buffer that
390 * OpenSSL passed.
391 */
392 psk_len = tls_session->psk.key_len;
393 memcpy(psk, tls_session->psk.key, psk_len);
394 tls_session_psk_reset(tls_session);
395
396 return (unsigned int)psk_len;
397 }
398
399 if (!conf->psk.identity) {
400 DEBUG("Rejecting the client, no fixed psk.identity set");
401 return 0;
402 }
403
404 /*
405 * Compare the identity against the fixed `psk.identity`, then
406 * copy the fixed `psk.key` into the `psk` buffer that OpenSSL
407 * passed.
408 */
409 if (strcmp(identity, conf->psk.identity) != 0) {
410 fr_tls_log_error("Supplied PSK identity %s does not match configuration. Rejecting.",
411 identity);
412 fr_tls_session_error_add(request, FR_ERROR_VALUE_PSK_IDENTITY_UNKNOWN);
413 return 0;
414 }
415
416 psk_len = talloc_array_length(conf->psk.key);
417 if (psk_len > max_psk_len) return 0;
418
419 memcpy(psk, conf->psk.key, psk_len);
420
421 return (unsigned int)psk_len;
422}
423
424/** Process the result of `load psk`
425 *
426 * The function runs in the subrequest, once the section has finished.
427 * The interpreter frees the subrequest when the function returns, so the
428 * function copies the key out of the reply and into the session. The
429 * function logs every error, because the function runs on the request's
430 * own stack rather than on the OpenSSL fibre. fr_tls_session_psk_server_cb()
431 * then only copies the key into the `psk` buffer that OpenSSL passed.
432 *
433 * @param[in] request The subrequest that ran the section.
434 * @param[in] uctx The #fr_tls_session_t that the section ran for.
435 * @return UNLANG_ACTION_CALCULATE_RESULT
436 */
437static unlang_action_t _tls_session_psk_load_resume(request_t *request, void *uctx)
438{
439 fr_tls_session_t *tls_session = talloc_get_type_abort(uctx, fr_tls_session_t);
440 fr_pair_t *vp;
441
442 fr_assert(tls_session->psk.state == FR_TLS_PSK_REQUESTED);
443
444 vp = fr_pair_find_by_da(&request->reply_pairs, NULL, attr_tls_packet_type);
445 if (!vp || (vp->vp_uint32 != enum_tls_packet_type_success->vb_uint32)) {
446 RWDEBUG("(TLS) Failed loading the pre-shared key, `load psk` did not return success");
447
448 /*
449 * `notfound` says that the policy does not know the
450 * identity, and an unknown identity is the peer's error.
451 * Any other failure is the policy's error.
452 */
453 fr_tls_session_error_add(request->parent,
454 (vp && (vp->vp_uint32 == enum_tls_packet_type_notfound->vb_uint32)) ?
455 FR_ERROR_VALUE_PSK_IDENTITY_UNKNOWN :
456 FR_ERROR_VALUE_LOAD_PSK_FAILED);
457 failed:
458 tls_session->psk.state = FR_TLS_PSK_FAILED;
460 }
461
462 vp = fr_pair_find_by_da(&request->reply_pairs, NULL, attr_tls_psk_key);
463 if (!vp || (vp->vp_length == 0)) {
464 RWDEBUG("(TLS) `load psk` returned success, but reply.TLS-PSK-Key is missing or empty");
465 fr_tls_session_error_add(request->parent, FR_ERROR_VALUE_PSK_EMPTY);
466 goto failed;
467 }
468
469 if (vp->vp_length > tls_session->psk.max_psk_len) {
470 RWDEBUG("(TLS) Rejecting reply.TLS-PSK-Key of %zu bytes, OpenSSL accepts at most %u bytes", vp->vp_length,
471 tls_session->psk.max_psk_len);
472 fr_tls_session_error_add(request->parent, FR_ERROR_VALUE_PSK_TOO_LONG);
473 goto failed;
474 }
475
476 MEM(tls_session->psk.key = talloc_memdup(tls_session, vp->vp_octets, vp->vp_length));
477 tls_session->psk.key_len = vp->vp_length;
478 tls_session->psk.state = FR_TLS_PSK_SUCCESS;
479
480 RDEBUG2("(TLS) Loaded a %zu-byte pre-shared key", vp->vp_length);
481
483}
484
485/** Push a `load psk` call into the current request, using a subrequest
486 *
487 * tls_session_async_handshake_cont() calls the function once the
488 * handshake has paused, after the pushes for pending session cache
489 * sections and before the push for a pending `verify certificate`
490 * section.
491 *
492 * @param[in] request The current request.
493 * @param[in] tls_session The current TLS session.
494 * @return
495 * - UNLANG_ACTION_CALCULATE_RESULT on noop.
496 * - UNLANG_ACTION_PUSHED_CHILD on success.
497 * - UNLANG_ACTION_FAIL on failure.
498 */
499unlang_action_t fr_tls_session_psk_pending_push(request_t *request, fr_tls_session_t *tls_session)
500{
501 fr_tls_conf_t *conf = tls_session->conf;
502 request_t *child;
503 fr_pair_t *identity;
505
506 if (tls_session->psk.state != FR_TLS_PSK_REQUESTED) return UNLANG_ACTION_CALCULATE_RESULT;
507
508 fr_assert(conf->virtual_server);
509
510 /*
511 * fr_tls_session_psk_server_cb() added the `TLS-PSK-Identity` pair to
512 * the request before pausing the handshake.
513 */
514 identity = fr_pair_find_by_da(&request->request_pairs, NULL, attr_tls_psk_identity);
515 fr_assert(identity);
516
517 RDEBUG2("(TLS) Loading the pre-shared key for identity \"%pV\"", &identity->data);
518
519 MEM(child = tls_subrequest_alloc(request, enum_tls_packet_type_load_psk->vb_uint32,
520 &tls_session->session_id));
521
522 /*
523 * Add extra pairs to the subrequest
524 */
525 fr_tls_session_extra_pairs_copy_to_child(child, tls_session);
526
527 fr_pair_append(&child->request_pairs, fr_pair_copy(child->request_ctx, identity));
528
529 /*
530 * Push the call to the TLS virtual server into the child.
531 */
532 ua = fr_tls_call_push(child, _tls_session_psk_load_resume, conf, tls_session, false);
533 if (ua == UNLANG_ACTION_FAIL) {
534 REDEBUG("(TLS) Failed calling TLS virtual server");
535 talloc_free(child);
536 return UNLANG_ACTION_FAIL;
537 }
538
539 return ua;
540}
541#endif /* PSK_MAX_IDENTITY_LEN */
542
543/** Record a TLS alert in a pair list
544 *
545 * A TLS Alert says why the handshake ended, so we only keep the last one.
546 *
547 * A peer can send multiple alerts, and if we left earlier `Alert` in
548 * the list, the policies would be looking at the wrong one.
549 *
550 * When we receive a TLS Alert, it gets copied into the `request`
551 * list. When we send a TLS Alert, it gets copied into the `reply`
552 * list.
553 *
554 * We also update `session-state.Error` to describe the TLS Alert.
555 * See fr_tls_session_error_add().
556 *
557 * @param[in] request to log through. A NULL request is ignored,
558 * because several OpenSSL callbacks run without one.
559 * @param[in] list_ctx the pair which holds the list, either
560 * `request->request_ctx` or `request->reply_ctx`.
561 * @param[in] prefix names the list in the log line.
562 * @param[in] level of the alert, warning or fatal.
563 * @param[in] description of the alert.
564 */
565static void tls_session_alert_pair_add(request_t *request, fr_pair_t *list_ctx, char const *prefix,
566 uint8_t level, uint8_t description)
567{
568 fr_pair_t *alert, *vp;
569
570 if (!request) return;
571
572 fr_pair_delete_by_da(&list_ctx->vp_group, attr_tls_alert);
573
574 MEM(fr_pair_append_by_da(list_ctx, &alert, &list_ctx->vp_group, attr_tls_alert) >= 0);
575
576 MEM(fr_pair_append_by_da(alert, &vp, &alert->vp_group, attr_tls_alert_level) >= 0);
577 vp->vp_uint8 = level;
578
579 MEM(fr_pair_append_by_da(alert, &vp, &alert->vp_group, attr_tls_alert_description) >= 0);
580 vp->vp_uint8 = description;
581
582 RDEBUG2("(TLS) Adding %s%pP", prefix, alert);
583}
584
585
586DIAG_OFF_OPTIONAL(used-but-marked-unused) /* Fix spurious warnings for sk_ macros */
587/** Record session state changes
588 *
589 * Called by OpenSSL whenever the session state changes, an alert is received or an error occurs.
590 *
591 * @param[in] ssl session.
592 * @param[in] where Which context the callback is being called in.
593 * See https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set_info_callback.html
594 * for additional info.
595 * @param[in] ret 0 if an error occurred, or the alert type if an alert was received.
596 */
597void fr_tls_session_info_cb(SSL const *ssl, int where, int ret)
598{
599 char const *role, *state;
600 request_t *request = SSL_get_ex_data(ssl, FR_TLS_EX_INDEX_REQUEST);
601
602 /*
603 * OpenSSL runs the info callback from inside a handshake round,
604 * and the library binds the request across a round.
605 */
606 fr_assert(request != NULL);
607
608 if ((where & ~SSL_ST_MASK) & SSL_ST_CONNECT) {
609 role = "Client ";
610 } else if (((where & ~SSL_ST_MASK)) & SSL_ST_ACCEPT) {
611 role = "Server ";
612 } else {
613 role = "";
614 }
615
616 state = SSL_state_string_long(ssl);
617 state = state ? state : "<INVALID>";
618
619 if ((where & SSL_CB_LOOP) || (where & SSL_CB_HANDSHAKE_START) || (where & SSL_CB_HANDSHAKE_DONE)) {
620 if (RDEBUG_ENABLED3) {
621 char const *abbrv = SSL_state_string(ssl);
622 size_t len;
623
624 /*
625 * Trim crappy OpenSSL state strings...
626 */
627 len = strlen(abbrv);
628 if ((len > 1) && (abbrv[len - 1] == ' ')) len--;
629
630 RDEBUG3("(TLS) Handshake state [%.*s] - %s%s", (int)len, abbrv, role, state);
631
632#ifdef OPENSSL_NO_SSL_TRACE
633 {
634 STACK_OF(SSL_CIPHER) *server_ciphers;
635 STACK_OF(SSL_CIPHER) *client_ciphers;
636
637 /*
638 * After a ClientHello, list all the proposed ciphers
639 * from the client.
640 *
641 * Only do this if we don't have SSL_trace() as
642 * SSL_trace() prints this information and we don't
643 * want to duplicate it.
644 */
645 if (SSL_get_state(ssl) == TLS_ST_SR_CLNT_HELLO &&
646 (client_ciphers = SSL_get_client_ciphers(ssl))) {
647 int i;
648 int num_ciphers;
649 const SSL_CIPHER *this_cipher;
650
651 server_ciphers = SSL_get_ciphers(ssl);
652 /*
653 * These are printed on startup, so not usually
654 * required.
655 */
656 RDEBUG4("(TLS) Our preferred ciphers (by priority)");
657 if (RDEBUG_ENABLED4) {
658 RINDENT();
659 num_ciphers = sk_SSL_CIPHER_num(server_ciphers);
660 for (i = 0; i < num_ciphers; i++) {
661 this_cipher = sk_SSL_CIPHER_value(server_ciphers, i);
662 RDEBUG4("(TLS) [%i] %s", i, SSL_CIPHER_get_name(this_cipher));
663 }
664 REXDENT();
665 }
666
667 /*
668 * Print information about the client's
669 * handshake message.
670 */
671 if (RDEBUG_ENABLED3) {
672 RDEBUG3("(TLS) Client's preferred ciphers (by priority)");
673 RINDENT();
674 num_ciphers = sk_SSL_CIPHER_num(client_ciphers);
675 for (i = 0; i < num_ciphers; i++) {
676 this_cipher = sk_SSL_CIPHER_value(client_ciphers, i);
677 RDEBUG3("(TLS) [%i] %s", i, SSL_CIPHER_get_name(this_cipher));
678 }
679 REXDENT();
680 }
681 }
682 }
683# endif
684 } else {
685 RDEBUG2("(TLS) Handshake state - %s%s (%u)", role, state, SSL_get_state(ssl));
686 }
687 return;
688 }
689
690 if (where & SSL_CB_ALERT) {
691 if ((ret & 0xff) == SSL_AD_CLOSE_NOTIFY) return;
692
693 /*
694 * We got an alert...
695 */
696 if (where & SSL_CB_READ) {
697 REDEBUG("(TLS) Client sent %s TLS alert (%i) - %s", SSL_alert_type_string_long(ret),
698 ret & 0xff, SSL_alert_desc_string_long(ret));
699
700 /*
701 * Offer helpful advice... Should be expanded.
702 */
703 switch (ret & 0xff) {
704 case TLS1_AD_UNKNOWN_CA:
705 REDEBUG("(TLS) Verify the client has a copy of the server's Certificate "
706 "Authority (CA) installed, and trusts that CA");
707 break;
708
709 default:
710 break;
711 }
712
713 /*
714 * The alert level is packed into the high octet of `ret`. The alert
715 * description is packed into the low octet.
716 *
717 * A peer can send alerts are multiple points in the handshake, so
718 * earlier alerts are removed before the latest one is added.
719 *
720 * We could just find an earlier alert and update its members, but that's
721 * more code.
722 */
723 tls_session_alert_pair_add(request, request->request_ctx, "",
724 (ret >> 8) & 0xff, ret & 0xff);
725 fr_tls_session_error_add(request, FR_ERROR_VALUE_RECEIVED_ALERT);
726 /*
727 * We're sending the client an alert.
728 */
729 } else {
730 REDEBUG("(TLS) Sending client %s TLS alert (%i) - %s",
731 SSL_alert_type_string_long(ret), ret & 0xff, SSL_alert_desc_string_long(ret));
732
733 /*
734 * Offer helpful advice... Should be expanded.
735 */
736 switch (ret & 0xff) {
737 case TLS1_AD_PROTOCOL_VERSION:
738 REDEBUG("(TLS) Client requested a TLS protocol version that is not "
739 "enabled or not supported. Upgrade FreeRADIUS + OpenSSL to their latest "
740 "versions and/or adjust 'tls_max_version'/'tls_min_version' if you want "
741 "authentication to succeed");
742 break;
743
744 default:
745 break;
746 }
747
748 /*
749 * A sent alert goes in the reply list, where a received one
750 * goes in the request list. `ret` packs the two octets the
751 * same way in both directions.
752 */
753 tls_session_alert_pair_add(request, request->reply_ctx, "reply.",
754 (ret >> 8) & 0xff, ret & 0xff);
755 fr_tls_session_error_add(request, FR_ERROR_VALUE_SENT_ALERT);
756 }
757 return;
758 }
759
760 if (where & SSL_CB_EXIT) {
761 if (ret == 0) {
762 REDEBUG("(TLS) Handshake exit state %s%s", role, state);
763 return;
764 }
765
766 if (ret < 0) {
767 if (SSL_want_read(ssl)) {
768 RDEBUG2("(TLS) Need more data from client"); /* State same as previous call, don't print */
769 return;
770 }
771 REDEBUG("(TLS) Handshake exit state %s%s", role, state);
772 }
773 }
774}
775DIAG_ON_OPTIONAL(used-but-marked-unused)
776
777/** Print a message to the request or global log detailing handshake state
778 *
779 * @param[in] request The current #request_t.
780 * @param[in] tls_session The current TLS session.
781 */
782static void session_msg_log(request_t *request, fr_tls_session_t *tls_session, uint8_t const *data, size_t data_len)
783{
784 char const *version, *content_type;
785 char const *str_details1 = NULL;
786 char const *str_details2 = NULL;
787 char unknown_version[32];
788 char unknown_content_type[32];
789 char unknown_alert_level[32];
790 char unknown_alert_description[32];
791 char unknown_handshake_type[32];
792
793 /*
794 * Both callers hold a request: fr_tls_session_msg_cb() takes it
795 * off the SSL *, and fr_tls_session_alert_send() is handed one.
796 */
797 fr_assert(request != NULL);
798
799 /*
800 * Don't print this out in the normal course of
801 * operations.
802 */
803 if (!RDEBUG_ENABLED2) return;
804
805 if (((size_t)tls_session->info.version >= NUM_ELEMENTS(tls_version_str)) ||
806 !tls_version_str[tls_session->info.version]) {
807 snprintf(unknown_version, sizeof(unknown_version), "unknown_tls_version_0x%04x",
808 (unsigned int) tls_session->info.version);
809 version = unknown_version;
810 } else {
811 version = tls_version_str[tls_session->info.version];
812 }
813
814 /*
815 * TLS 1.0, 1.1, 1.2 content types are the same as SSLv3
816 */
817 if (((size_t)tls_session->info.content_type >= NUM_ELEMENTS(tls_content_type_str)) ||
818 !tls_content_type_str[tls_session->info.content_type]) {
819 snprintf(unknown_content_type, sizeof(unknown_content_type),
820 "unknown_content_type_0x%04x", (unsigned int) tls_session->info.content_type);
821 content_type = unknown_content_type;
822 } else {
823 content_type = tls_content_type_str[tls_session->info.content_type];
824 }
825
826 if (tls_session->info.content_type == SSL3_RT_ALERT) {
827 if (tls_session->info.record_len == 2) {
828 switch (tls_session->info.alert_level) {
829 case SSL3_AL_WARNING:
830 str_details1 = "warning";
831 break;
832 case SSL3_AL_FATAL:
833 str_details1 = "fatal";
834 break;
835
836 default:
837 snprintf(unknown_alert_level, sizeof(unknown_alert_level),
838 "unknown_alert_level_0x%04x", tls_session->info.alert_level);
839 str_details1 = unknown_alert_level;
840 break;
841 }
842
843 if (((size_t)tls_session->info.alert_description >= NUM_ELEMENTS(tls_alert_description_str)) ||
844 !tls_alert_description_str[tls_session->info.alert_description]) {
845 snprintf(unknown_alert_description, sizeof(unknown_alert_description),
846 "unknown_alert_0x%04x", tls_session->info.alert_description);
847 str_details2 = unknown_alert_description;
848 } else {
849 str_details2 = tls_alert_description_str[tls_session->info.alert_description];
850 }
851 } else {
852 str_details1 = "unknown_alert_level";
853 str_details2 = "unknown_alert";
854 }
855 }
856
857 if ((size_t)tls_session->info.content_type == SSL3_RT_HANDSHAKE) {
858 if (tls_session->info.record_len > 0) {
859 /*
860 * Range guard not needed due to size of array
861 * and underlying type.
862 */
863 if (!tls_handshake_type_str[tls_session->info.handshake_type]) {
864 snprintf(unknown_handshake_type, sizeof(unknown_handshake_type),
865 "unknown_handshake_type_0x%02x", tls_session->info.handshake_type);
866 str_details1 = unknown_handshake_type;
867 } else {
868 str_details1 = tls_handshake_type_str[tls_session->info.handshake_type];
869 }
870 }
871 }
872
873 snprintf(tls_session->info.info_description, sizeof(tls_session->info.info_description),
874 "%s %s, %s[length %lu]%s%s%s%s",
875 tls_session->info.origin ? ">>> send" : "<<< recv",
876 version,
877 content_type,
878 (unsigned long)tls_session->info.record_len,
879 str_details1 ? ", " : "",
880 str_details1 ? str_details1 : "",
881 str_details2 ? ", " : "",
882 str_details2 ? str_details2 : "");
883
884 /*
885 * Print out information about the record and print the
886 * data at higher debug levels.
887 */
888 if (RDEBUG_ENABLED4) {
889 RHEXDUMP4(data, data_len, "(TLS) %s", tls_session->info.info_description);
890 } else {
891 RDEBUG2("(TLS) %s", tls_session->info.info_description);
892 }
893}
894
895/** Record the progression of the TLS handshake
896 *
897 * This callback is called by OpenSSL whenever a protocol message relating to a handshake is sent
898 * or received.
899 *
900 * This function copies state information from the various arguments into the state->info
901 * structure of the #fr_tls_session_t, to allow us to track the progression of the handshake.
902 *
903 * @param[in] write_p
904 * - 0 when a message has been received.
905 * - 1 when a message has been sent.
906 *
907 * @param[in] msg_version The TLS version negotiated, should be one of:
908 * - TLS1_VERSION
909 * - TLS1_1_VERSION
910 * - TLS1_2_VERSION
911 * - TLS1_3_VERSION
912 *
913 * @param[in] content_type One of the contentType values defined for TLS:
914 * - SSL3_RT_CHANGE_CIPHER_SPEC (20)
915 * - SSL3_RT_ALERT (21)
916 * - SSL3_RT_HANDSHAKE (22)
917 * - TLS1_RT_HEARTBEAT (24)
918 *
919 * @param[in] inbuf The raw protocol message.
920 * @param[in] len Length of the raw protocol message.
921 * @param[in] ssl The SSL session.
922 * @param[in] arg The #fr_tls_session_t holding the SSL session.
923 */
924void fr_tls_session_msg_cb(int write_p, int msg_version, int content_type,
925 void const *inbuf, size_t len,
926 SSL *ssl, void *arg)
927{
928 uint8_t const *buf = inbuf;
929 fr_tls_session_t *tls_session = talloc_get_type_abort(arg, fr_tls_session_t);
930 request_t *request = fr_tls_session_request(tls_session->ssl);
931
932 /*
933 * OpenSSL runs the message callback for every record it reads
934 * or writes, and every one of those happens while the library
935 * has the request bound. _fr_dtls_timer_expired() binds across
936 * DTLSv1_handle_timeout() for exactly this reason.
937 */
938 fr_assert(request != NULL);
939
940 /*
941 * Mostly to check for memory corruption...
942 */
943 if (!fr_cond_assert(tls_session->ssl == ssl)) {
944 REDEBUG("(TLS) fr_tls_session_t and ssl arg do not match in fr_tls_session_msg_cb");
945 fr_tls_session_error_alert(request, tls_session,
946 FR_ERROR_VALUE_SESSION_MISMATCH, SSL_AD_INTERNAL_ERROR);
947 tls_session->invalid = true;
948 return;
949 }
950
951 /*
952 * As per https://tools.ietf.org/html/rfc7568
953 *
954 * We explicitly disable SSLv2/v3, hence the asserts.
955 */
956#ifdef SSL2_VERSION
957 if (!fr_cond_assert(msg_version != SSL2_VERSION)) {
958 REDEBUG("(TLS) Invalid version (SSLv2) in handshake");
959 fr_tls_session_error_alert(request, tls_session,
960 FR_ERROR_VALUE_INVALID_VERSION_SSLV2, SSL_AD_PROTOCOL_VERSION);
961 tls_session->invalid = true;
962 return;
963 }
964#endif
965
966#ifdef SSL3_VERSION
967 if (!fr_cond_assert(msg_version != SSL3_VERSION)) {
968 REDEBUG("(TLS) Invalid version (SSLv3) in handshake");
969 fr_tls_session_error_alert(request, tls_session,
970 FR_ERROR_VALUE_INVALID_VERSION_SSLV3, SSL_AD_PROTOCOL_VERSION);
971 tls_session->invalid = true;
972 return;
973 }
974#endif
975
976 /*
977 * OpenSSL >= 1.0.2 calls this function with 'pseudo'
978 * content types. Which breaks our tracking of
979 * the SSL Session state.
980 */
981 if ((msg_version == 0) && (content_type > UINT8_MAX)) {
982 REDEBUG4("(TLS) Ignoring fr_tls_session_msg_cb call with pseudo content type %i, version %i",
983 content_type, msg_version);
984 return;
985 }
986
987 if ((write_p != 0) && (write_p != 1)) {
988 REDEBUG4("(TLS) Ignoring fr_tls_session_msg_cb call with invalid write_p %d", write_p);
989 return;
990 }
991
992 /*
993 * 0 - received (from peer)
994 * 1 - sending (to peer)
995 */
996 tls_session->info.origin = write_p;
997 tls_session->info.content_type = content_type;
998 tls_session->info.record_len = len;
999 tls_session->info.version = msg_version;
1000 tls_session->info.initialized = true;
1001
1002 switch (content_type) {
1003 case SSL3_RT_ALERT:
1004 if (len < 2) {
1005 invalid_alert:
1006 REDEBUG("(TLS) Invalid TLS Alert. Closing connection");
1007 fr_tls_session_error_alert(request, tls_session,
1008 FR_ERROR_VALUE_INVALID_RECORD_LENGTH, SSL_AD_DECODE_ERROR);
1009 tls_session->invalid = true;
1010 return;
1011 }
1012
1013 tls_session->info.alert_level = buf[0];
1014 tls_session->info.alert_description = buf[1];
1015 tls_session->info.handshake_type = 0x00;
1016 break;
1017
1018 case SSL3_RT_HANDSHAKE:
1019 if (!len) goto invalid_alert;
1020
1021 tls_session->info.handshake_type = buf[0];
1022 tls_session->info.alert_level = 0x00;
1023 tls_session->info.alert_description = 0x00;
1024 break;
1025
1026#ifdef SSL3_RT_HEARTBEAT
1027 case TLS1_RT_HEARTBEAT:
1028 uint8_t *p = buf;
1029
1030 if ((len >= 3) && (p[0] == 1)) {
1031 size_t payload_len;
1032
1033 payload_len = fr_nbo_to_uint16(p + 1);
1034 if ((payload_len + 3) > len) {
1035 tls_session->invalid = true;
1036 REDEBUG("(TLS) OpenSSL Heartbeat attack detected. Closing connection");
1037 fr_tls_session_error_alert(request, tls_session,
1038 FR_ERROR_VALUE_HEARTBEAT_OVERFLOW, SSL_AD_DECODE_ERROR);
1039 return;
1040 }
1041 }
1042 break;
1043#endif
1044 default:
1045 break;
1046 }
1047
1048 /*
1049 * Manually track when records are encrypted. Once records are encrypted, we can't manually
1050 * create a TLS alert. OpenSSL doesn't have an API to send alerts. And it doesn't have an API
1051 * to tell us when the records are encrypted.
1052 */
1053 switch (content_type) {
1054 /*
1055 * Everything after ChangeCipherSpec is encrypted.
1056 */
1057 case SSL3_RT_CHANGE_CIPHER_SPEC:
1058 if (write_p != TLS_INFO_ORIGIN_RECORD_SENT) break;
1059 if (tls_session->write_encrypted) break;
1060
1061 tls_session->write_encrypted = true;
1062 RDEBUG3("(TLS) The records we write are encrypted, from the ChangeCipherSpec onwards");
1063 break;
1064
1065 /*
1066 * For TLS 1.3, everything after ServerHello is encrypted. After ServerHello, SSL_version()
1067 * finally returns the correct TLS version number which was negotiated. Before ServerHello,
1068 * SSL_version() returns the highest allowed TLS version.
1069 */
1070 case SSL3_RT_HANDSHAKE:
1071 if (tls_session->info.handshake_type != SSL3_MT_SERVER_HELLO) break;
1072 if (SSL_version(ssl) < TLS1_3_VERSION) break;
1073 if (tls_session->write_encrypted) break;
1074
1075 tls_session->write_encrypted = true;
1076 RDEBUG3("(TLS) The records we write are encrypted, from the ServerHello onwards");
1077 break;
1078
1079 default:
1080 break;
1081 }
1082
1083 session_msg_log(request, tls_session, (uint8_t const *)inbuf, len);
1084
1085#ifndef OPENSSL_NO_SSL_TRACE
1086 if (RDEBUG_ENABLED3) {
1087 SSL_trace(tls_session->info.origin,
1088 tls_session->info.version,
1089 tls_session->info.content_type,
1090 inbuf, len,
1091 ssl,
1092 request ?
1093 fr_tls_request_log_bio(request, L_DBG, L_DBG_LVL_3) :
1094 fr_tls_global_log_bio(L_DBG, L_DBG_LVL_3));
1095 }
1096#endif
1097}
1098
1099/*
1100 * By setting the environment variable SSLKEYLOGFILE to a filename keying
1101 * material will be exported that you may use with Wireshark to decode any
1102 * TLS flows. Please see the following for more details:
1103 *
1104 * https://gitlab.com/wireshark/wireshark/-/wikis/TLS#tls-decryption
1105 *
1106 * An example logging session is (you should delete the file on each run):
1107 *
1108 * rm -f /tmp/sslkey.log; env SSLKEYLOGFILE=/tmp/sslkey.log freeradius -X | tee /tmp/debug
1109 *
1110 * Note that we rely on the OS to check file permissions. If the
1111 * caller can run radiusd, then they can only write to files which
1112 * they own. If radiusd is running as root, then only root can
1113 * change the environment variables for radiusd.
1114 */
1115void fr_tls_session_keylog_cb(const SSL *ssl, const char *line)
1116{
1117 int fd;
1118 size_t len;
1119 const char *filename;
1120 char buffer[64 + 2*SSL3_RANDOM_SIZE + 2*SSL_MAX_MASTER_KEY_LENGTH];
1121
1122 /*
1123 * Prefer the environment variable definition to the
1124 * configuration file. This allows for "one-shot"
1125 * dumping of EAP keys when you know you're not using
1126 * RadSec, and you don't want to edit the configuration.
1127 */
1128 filename = getenv("SSLKEYLOGFILE");
1129 if (!filename) {
1130 fr_tls_conf_t *conf;
1131
1132 conf = (fr_tls_conf_t *)SSL_get_ex_data(ssl, FR_TLS_EX_INDEX_CONF);
1133 if (!conf || !conf->keylog_file || !*conf->keylog_file) return;
1134
1135 filename = conf->keylog_file;
1136 }
1137
1138 /*
1139 * We write all of the data at once. This is *generally*
1140 * atomic on most systems.
1141 */
1142 len = strlen(line);
1143 if ((len + 1) > sizeof(buffer)) {
1144 DEBUG("SSLKEYLOGFILE buffer not large enough, max %lu, required %lu", sizeof(buffer), len + 1);
1145 return;
1146 }
1147
1148 /*
1149 * Add a \n, which means that in order to write() the
1150 * buffer AND the trailing \n, we have to place both
1151 * strings into the same buffer.
1152 */
1153 memcpy(buffer, line, len);
1154 buffer[len] = '\n';
1155
1156 fd = open(filename, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
1157 if (fd < 0) {
1158 DEBUG("Failed to open file %s: %s", filename, strerror(errno));
1159 return;
1160 }
1161
1162 /*
1163 * This should work in most situations.
1164 */
1165 if (write(fd, buffer, len + 1) < 0) {
1166 DEBUG("Failed to write to file %s: %s", filename, strerror(errno));
1167 }
1168
1169 close(fd);
1170}
1171
1172/** Check if all TLS initialization has finished.
1173 *
1174 * SSL_is_init_finished() tells us if the TLS handshake has finished,
1175 * which is enough for TLS 1.2, or TLS 1.3 without session tickets, or
1176 * TLS 1.3 with stateful session tickets.
1177 *
1178 * For TLS 1.3 with stateless session tickets, the ticket is sent
1179 * after the handshake has completed. The application gets to
1180 * send/recv its application data only after the handshake has
1181 * finished, the stateless session ticket has been received, and after
1182 * the `load session` has been run.
1183 *
1184 * Callers outside this library MUST use this function rather than
1185 * SSL_is_init_finished().
1186 *
1187 * @param[in] tls_session to check.
1188 * @return
1189 * - true if every part of the setup has finished.
1190 * - false if OpenSSL is still handshaking, or a `load session` which
1191 * the caller has to wait for has not run yet.
1192 */
1193bool fr_tls_session_is_init_finished(fr_tls_session_t *tls_session)
1194{
1195 fr_tls_conf_t *conf;
1196
1197 if (!SSL_is_init_finished(tls_session->ssl)) return false;
1198
1199 /*
1200 * Stateless session tickets are what add a step after
1201 * OpenSSL is done, and only TLS 1.3 uses them here. Without
1202 * them there is nothing else to wait for.
1203 */
1204 if (tls_session->info.version != TLS1_3_VERSION) return true;
1205
1206 if (!tls_session->cache) return true;
1207
1208 conf = tls_session->conf;
1209 if (!(conf->cache.mode & FR_TLS_TICKET_STATELESS)) return true;
1210
1211 /*
1212 * If we're not a server, then we're a client, and we
1213 * need to receive a ticket. For TLS 1.3 with stateless
1214 * session tickets, the TLS handshake is finished, and
1215 * then we get a ticket. So we're not done until we see
1216 * a ticket.
1217 *
1218 * We can either wait forever for a ticket, or notice
1219 * that receiption of application data means that the
1220 * ticket was sent (or not).
1221 */
1222 if (!SSL_is_server(tls_session->ssl)) {
1223 return tls_session->session_ticket_received || tls_session->seen_application_data;
1224 }
1225
1226 /*
1227 * Something has requested `load session`, but it hasn't
1228 * yet been run. Once that section completes, its state
1229 * returns to INIT. A session which never sends a ticket
1230 * is therefore also marked as finished.
1231 */
1232 return (tls_session->cache->load.state != FR_TLS_TICKET_STATEFUL_REQUESTED);
1233}
1234
1235/** Decrypt application data
1236 *
1237 * @note Handshake must have completed before this function may be called.
1238 *
1239 * Feed data from dirty_in to OpenSSL, and read the clean data into clean_out.
1240 *
1241 * @param[in] request The current #request_t.
1242 * @param[in] tls_session The current TLS session.
1243 * @return
1244 * - -1 on error.
1245 * - 1 if more fragments are required to fully reassemble the record for decryption.
1246 * - 0 if we decrypted a complete record.
1247 */
1248int fr_tls_session_recv(request_t *request, fr_tls_session_t *tls_session)
1249{
1250 int ret;
1251
1252 if (!tls_session->seen_application_data) {
1253 if (!SSL_is_init_finished(tls_session->ssl)) {
1254 REDEBUG("(TLS) Attempted to read application data before handshake completed");
1255 fr_tls_session_error_add(request, FR_ERROR_VALUE_APPLICATION_DATA_TOO_EARLY);
1256 return -1;
1257 }
1258
1259 /*
1260 * The handshake is over and we are about to move application
1261 * data, so we are past the point where a session ticket is
1262 * wanted. tls_ticket_stateful_store_cb() refuses any which arrive from
1263 * here on.
1264 */
1265 tls_session->seen_application_data = true;
1266 }
1267
1268 fr_tls_session_request_bind(tls_session->ssl, request);
1269
1270 /*
1271 * Nothing is copied here. The caller filled dirty_in, which
1272 * is into_ssl's producer cursor, so OpenSSL can already see
1273 * the record, and the BIO read callback reclaims the space as
1274 * OpenSSL consumes it.
1275 *
1276 * Init the clean_out buffer to store the decrypted data.
1277 */
1278 fr_tls_record_init(&tls_session->clean_out);
1279
1280 /*
1281 * Prevent spurious errors on the thread local error
1282 * stack causing SSL_get_error() to return SSL_ERROR_SSL
1283 * instead of what of the SSL_ERROR_WANT_* values.
1284 */
1285 ERR_clear_error();
1286
1287 /*
1288 * Read (and decrypt) the tunneled data from the
1289 * SSL session, and put it into the decrypted
1290 * data buffer.
1291 */
1292 ret = SSL_read(tls_session->ssl, fr_dbuff_current(&tls_session->clean_out),
1293 fr_dbuff_remaining(&tls_session->clean_out));
1294 if (ret < 0) {
1295 int code;
1296
1297 code = SSL_get_error(tls_session->ssl, ret);
1298 switch (code) {
1299 case SSL_ERROR_WANT_READ:
1300 RWDEBUG("(TLS) Peer indicated record was complete, but OpenSSL returned SSL_WANT_READ. "
1301 "Attempting to continue");
1302 ret = 1;
1303 goto finish;
1304
1305 case SSL_ERROR_WANT_WRITE:
1306 REDEBUG("(TLS) Error in fragmentation logic: SSL_WANT_WRITE");
1307 error:
1308 ret = -1;
1309 goto finish;
1310
1311 case SSL_ERROR_NONE:
1312 RDEBUG2("(TLS) No application data received. Assuming handshake is continuing...");
1313 ret = 0;
1314 break;
1315
1316 default:
1317 REDEBUG("(TLS) Error in fragmentation logic");
1318 fr_tls_log_io_error(request, code, "SSL_read (%s)", __FUNCTION__);
1319 goto error;
1320 }
1321 }
1322
1323 /*
1324 * Passed all checks, successfully decrypted data
1325 */
1326 fr_dbuff_advance(&tls_session->clean_out, (size_t) ret);
1327 ret = 0;
1328
1329 if (RDEBUG_ENABLED3) {
1330 RHEXDUMP3(fr_dbuff_start(&tls_session->clean_out), fr_dbuff_used(&tls_session->clean_out),
1331 "(TLS) Decrypted TLS application data (%zu bytes)", fr_dbuff_used(&tls_session->clean_out));
1332 } else {
1333 RDEBUG2("(TLS) Decrypted TLS application data (%zu bytes)", fr_dbuff_used(&tls_session->clean_out));
1334 }
1335finish:
1336 fr_tls_session_request_unbind(tls_session->ssl);
1337
1338 return ret;
1339}
1340
1341/** Encrypt application data
1342 *
1343 * @note Handshake must have completed before this function may be called.
1344 *
1345 * Take cleartext data from clean_in, and feed it to OpenSSL, reading
1346 * the encrypted data into dirty_out.
1347 *
1348 * @param[in] request The current request.
1349 * @param[in] tls_session The current TLS session.
1350 * @return
1351 * - -1 on failure.
1352 * - 0 on success.
1353 */
1354int fr_tls_session_send(request_t *request, fr_tls_session_t *tls_session)
1355{
1356 int ret = 0;
1357
1358 if (!tls_session->seen_application_data) {
1359 if (!SSL_is_init_finished(tls_session->ssl)) {
1360 REDEBUG("(TLS) Attempted to write application data before handshake completed");
1361 fr_tls_session_error_add(request, FR_ERROR_VALUE_APPLICATION_DATA_TOO_EARLY);
1362 return -1;
1363 }
1364
1365 tls_session->seen_application_data = true;
1366 }
1367
1368 fr_tls_session_request_bind(tls_session->ssl, request);
1369
1370 /*
1371 * If there's un-encrypted data in 'clean_in', then write
1372 * that data to the SSL session, and then call the BIO function
1373 * to get that encrypted data from the SSL session, into
1374 * a buffer which we can then package into an EAP packet.
1375 *
1376 * Based on Server's logic this clean_in is expected to
1377 * contain the data to send to the client.
1378 */
1379 if (fr_dbuff_used(&tls_session->clean_in) > 0) {
1380 size_t used = fr_dbuff_used(&tls_session->clean_in);
1381
1382 /*
1383 * Ensure spurious errors aren't printed
1384 */
1385 ERR_clear_error();
1386
1387 if (RDEBUG_ENABLED3) {
1388 RHEXDUMP3(fr_dbuff_start(&tls_session->clean_in), used,
1389 "(TLS) TLS application data to encrypt (%zu bytes)", used);
1390 } else {
1391 RDEBUG2("(TLS) TLS application data to encrypt (%zu bytes)", used);
1392 }
1393
1394 ret = SSL_write(tls_session->ssl, fr_dbuff_start(&tls_session->clean_in), used);
1395 if (ret < 0) {
1396 /*
1397 * ret<0 means that we have a real error.
1398 *
1399 * ret=0 means the "error" is SSL_WANT_READ, SSL_WANT_WRITE, etc.
1400 */
1401 ret = fr_tls_log_io_error(request, SSL_get_error(tls_session->ssl, ret),
1402 "SSL_write (%s)", __FUNCTION__);
1403 goto finish;
1404 }
1405
1406 /*
1407 * SSL_MODE_ENABLE_PARTIAL_WRITE is not set, so SSL_write()
1408 * either takes everything or fails. The whole buffer is
1409 * therefore consumed.
1410 */
1411 fr_assert((size_t) ret == used);
1412 fr_tls_record_init(&tls_session->clean_in);
1413
1414 /*
1415 * SSL_write() passes the encrypted record in
1416 * dirty_in to the BIO callback, which put the
1417 * output data into from_ssl. We're therefore
1418 * done here.
1419 */
1420 ret = 0;
1421 }
1422
1423finish:
1424 fr_tls_session_request_unbind(tls_session->ssl);
1425
1426 return ret;
1427}
1428
1429/** Record a failure which FreeRADIUS itself decided
1430 *
1431 * The `session-state` list is where these go, because the list is what
1432 * survives from one round of the handshake to the next, and because it is
1433 * the list which `fail session { ... }` is given.
1434 *
1435 * Errors append rather than replace. A record which FreeRADIUS refuses
1436 * marks the session invalid, and the round after that reports
1437 * `Session-Invalid`. Replacing would keep that second report and lose the
1438 * refusal which caused it, which is the part an administrator needs.
1439 *
1440 * @param[in] request to add the error to. A NULL request is ignored,
1441 * because several OpenSSL callbacks run without one.
1442 * @param[in] error an `FR_ERROR_VALUE_*` value from
1443 * `protocol/tls/freeradius.h`, which is generated from
1444 * `share/dictionary/tls/dictionary.freeradius`.
1445 */
1446void fr_tls_session_error_add(request_t *request, uint32_t error)
1447{
1448 fr_pair_t *vp;
1449
1450 if (!request) return;
1451
1453 vp->vp_uint32 = error;
1454
1455 RDEBUG2("(TLS) request.%pP", vp);
1456}
1457
1458/** Instruct fr_tls_session_async_handshake to create a synthesised TLS alert record and send it to the peer
1459 *
1460 */
1461int fr_tls_session_alert(request_t *request, fr_tls_session_t *session, uint8_t level, uint8_t description)
1462{
1463 fr_assert(request != NULL);
1464
1465 if (session->alerts_sent > 3) return -1; /* Some kind of state machine brokenness */
1466
1467 /*
1468 * Ignore an alert which has lower severity than the one already queued.
1469 *
1470 * Two alerts of the same severity means the first one is the cause, and the second one is a
1471 * later round noticing the damage. fr_tls_session_msg_cb() refuses a record and marks the
1472 * session invalid, and the round after that reports FR_ERROR_VALUE_SESSION_INVALID. The first
1473 * alert says what was wrong with the record, which is the part the peer can act on.
1474 */
1475 if (session->pending_alert && (level <= session->pending_alert_level)) return 0;
1476
1477 /*
1478 * Check our internal flag is write_encrypted. We track that above in fr_tls_session_msg_cb()
1479 *
1480 * Refusing here rather than when the alert is sent lets the caller act on the refusal. A caller
1481 * which queued the alert in order to reject the session has to fail the session some other way,
1482 * and both callers outside this file already check the return code.
1483 *
1484 * The caller still records the error, so `fail session { ... }` reports the same reason either
1485 * way. However, the peer never gets the alert.
1486 */
1487 if (session->write_encrypted) {
1488 RDEBUG2("(TLS) Not sending TLS alert (%u), the records we write are already encrypted",
1489 description);
1490 return -1;
1491 }
1492
1493 session->pending_alert = true;
1494 session->pending_alert_level = level;
1495 session->pending_alert_description = description;
1496
1497 return 0;
1498}
1499
1500/** Record an application error, and queue a fatal TLS alert for sending to the peer.
1501 *
1502 * We can refuse handshakes for a number of policy or application-layer reasons. RFC9846 Section 6.2 says
1503 * that we should send an alert to the peer, and then close the connection.
1504 *
1505 * This function should be used only when OpenSSL hasn't already sent an alert of its own.
1506 *
1507 * fr_tls_session_alert_send() builds the alert by hand, and overwrites whatever OpenSSL left in
1508 * the buffer.
1509 *
1510 * @param[in] request to add the error to.
1511 * @param[in] session to queue the alert on.
1512 * @param[in] error an `FR_ERROR_VALUE_*` value, as for
1513 * fr_tls_session_error_add().
1514 * @param[in] description the TLS alert description to send. Pass
1515 * `SSL_AD_INTERNAL_ERROR` where no more specific
1516 * description fits the rule which was broken.
1517 */
1518void fr_tls_session_error_alert(request_t *request, fr_tls_session_t *session,
1519 uint32_t error, uint8_t description)
1520{
1521 fr_tls_session_error_add(request, error);
1522
1523 (void) fr_tls_session_alert(request, session, SSL3_AL_FATAL, description);
1524}
1525
1526static void fr_tls_session_alert_send(request_t *request, fr_tls_session_t *session)
1527{
1528#ifndef NDEBUG
1529 ssize_t slen;
1530#endif
1531
1532 /*
1533 * Update our internal view of the session
1534 */
1535 session->info.origin = TLS_INFO_ORIGIN_RECORD_SENT;
1536 session->info.content_type = SSL3_RT_ALERT;
1537 session->info.alert_level = session->pending_alert_level;
1538 session->info.alert_description = session->pending_alert_description;
1539
1540 /*
1541 * session_msg_log() reads both of these, and decodes the
1542 * level and the description only when the length says two.
1543 * Without them the log line reports whatever record came
1544 * before this one, which is not the alert it claims to
1545 * describe. They have to agree with the record written
1546 * below.
1547 */
1548 session->info.version = TLS1_VERSION;
1549 session->info.record_len = 2;
1550
1551 /*
1552 * Sending an alert over-rides whatever was in the
1553 * buffer, waiting to be sent. But for nearly all cases,
1554 * the from_ssl buffer will already be empty.
1555 *
1556 * The application then sees the data, and writes it to
1557 * the peer.
1558 */
1559 fr_tls_bio_dbuff_clear(session->from_ssl);
1560
1561#ifndef NDEBUG
1562 slen = /* only used for the assert below */
1563#endif
1564 fr_dbuff_in_bytes(fr_tls_bio_dbuff_in(session->from_ssl),
1565 (uint8_t) session->info.content_type,
1566 (uint8_t) 3, (uint8_t) 1, (uint8_t) 0, (uint8_t) 2,
1567 session->pending_alert_level,
1568 session->pending_alert_description);
1569 fr_assert(slen == 7);
1570
1571 /*
1572 * We're building the TLS Alert manually, so we have to
1573 * manually record it here.
1574 */
1575 tls_session_alert_pair_add(request, request->reply_ctx, "reply.",
1576 session->pending_alert_level, session->pending_alert_description);
1577 fr_tls_session_error_add(request, FR_ERROR_VALUE_SENT_ALERT);
1578
1579 session->pending_alert = false;
1580 session->alerts_sent++;
1581
1582 SSL_clear(session->ssl); /* Reset the SSL *, to allow the client to restart the session */
1583
1584 session_msg_log(request, session, fr_dbuff_current(session->dirty_out),
1585 fr_dbuff_remaining(session->dirty_out));
1586}
1587
1588/** Tell the peer about any pending errors before we close the connection.
1589 *
1590 * A connection which is about to close sends a `close_notify`, as RFC 9846 Section 6.1 says "Each party MUST
1591 * send a 'close_notify' alert before closing its write side of the connection, unless it has already sent
1592 * some error alert." If there's an error alert, then don't send that.
1593 *
1594 * - A queued fatal alert is an error, and we send that. The end of a handshake round sends any queued alert.
1595 * An error path does not reach the end of the round, so the "send alert" function has to be called
1596 * explicitly.
1597 *
1598 * - if there's no queued alert, then we just send a close_notify alert. OpenSSL doesn't provide any other
1599 * way to send a TLS alert to the peer.
1600 *
1601 * - If the handshake doesn't finish, then we can't send anything. The connection is likely not TLS, and
1602 * sending a TLS alert won't help.
1603 *
1604 * The application should send the remaining data, and then close the socket.
1605 *
1606 * @param[in] request to log against, and to bind while OpenSSL runs.
1607 * @param[in] session which is closing.
1608 */
1609void fr_tls_session_close_send(request_t *request, fr_tls_session_t *session)
1610{
1611 bool bound;
1612 int ret;
1613
1614 if (session->pending_alert) {
1615 fr_tls_session_alert_send(request, session);
1616 return;
1617 }
1618
1619 /*
1620 * We've already sent an error alert, and RFC 9846 Section 6.1 says we don't need to follow that
1621 * with a close_notify. OpenSSL alerts don't need to be counted, because they result in
1622 * handshake failures, and this function is never reached.
1623 */
1624 if (session->alerts_sent > 0) return;
1625
1626 if (!SSL_is_init_finished(session->ssl)) return;
1627
1628 /*
1629 * Make this function idempotent. The source of the fatal error calls us, and we might be called
1630 * again after `fail sessions { ... }` finishes. The application doesn't know what's up, so it
1631 * calls us just to be safe.
1632 */
1633 if (SSL_get_shutdown(session->ssl) & SSL_SENT_SHUTDOWN) return;
1634
1635 /*
1636 * A failure inside of a handshake results in fr_tls_session_msg_cb() being called, and it needs
1637 * the request bound. Do that here, if it wasn't already done/
1638 */
1639 bound = (fr_tls_session_request(session->ssl) != NULL);
1640 if (!bound) fr_tls_session_request_bind(session->ssl, request);
1641
1642 /*
1643 * Disable the OpenSSL quiet shutdown, so it sends close_notify. We need to do that on our
1644 * timeframe, so the quiet shutdown is on by default.
1645 *
1646 * OpenSSL drops a session from its internal cache (and maybe ours) when a connection closes
1647 * without seeing a `close_notify`.
1648 */
1649 SSL_set_quiet_shutdown(session->ssl, 0);
1650
1651 ret = SSL_shutdown(session->ssl);
1652
1653 /*
1654 * We're non-blocking, so a zero return is "we sent it, but we didn't see a response from the
1655 * peer", which is expected.
1656 */
1657 if (ret < 0) {
1658 RDEBUG2("(TLS) Failed sending close_notify");
1659 ERR_clear_error();
1660 } else {
1661 RDEBUG2("(TLS) Sending close_notify");
1662 }
1663
1664 if (!bound) fr_tls_session_request_unbind(session->ssl);
1665}
1666
1667/** Push an `establish session { ... }` call into the current request, using a subrequest
1668 *
1669 * @param[in] request The current request.
1670 * @param[in] conf TLS configuration.
1671 * @param[in] tls_session The current TLS session.
1672 * @return
1673 * - UNLANG_ACTION_PUSHED_CHILD on success.
1674 * - UNLANG_ACTION_FAIL on failure.
1675 */
1676static inline CC_HINT(always_inline)
1677unlang_action_t tls_establish_session_push(request_t *request, fr_tls_conf_t *conf, fr_tls_session_t *tls_session)
1678{
1679 request_t *child;
1680 unlang_action_t ua;
1681
1682 fr_assert(conf->virtual_server);
1683
1684 MEM(child = tls_subrequest_alloc(request, enum_tls_packet_type_establish_session->vb_uint32,
1685 &tls_session->session_id));
1686
1687 /*
1688 * Allocate a child, and set it up to call
1689 * the TLS virtual server.
1690 */
1691 ua = fr_tls_call_push(child, NULL, conf, tls_session, false);
1692 if (ua == UNLANG_ACTION_FAIL) {
1693 talloc_free(child);
1694 return UNLANG_ACTION_FAIL;
1695 }
1696
1697 return ua;
1698}
1699
1700/** Discard the session, once `fail session { ... }` has run
1701 *
1702 */
1703static unlang_action_t tls_session_fail_clear(request_t *request, void *uctx)
1704{
1705 fr_tls_session_t *tls_session = talloc_get_type_abort(uctx, fr_tls_session_t);
1706
1707 return fr_tls_ticket_stateful_clear_session(request, tls_session);
1708}
1709
1710/** The TLS session failed
1711 *
1712 * Runs `fail session { ... }`, so that the admin can run policies on
1713 * TLS connection failure. Once that's done, run `clear session` to
1714 * remove any cached session information.
1715 *
1716 * We can fail sessions without using session tickets and we can
1717 * remove session tickets without failing TLS negotiation.
1718 *
1719 * @note The caller MUST set the caller's own unlang result before calling
1720 * fr_tls_session_fail_session(). A pushed child returns to the caller's
1721 * caller with that result already in place.
1722 *
1723 * @param[in] request to run the sections in.
1724 * @param[in] tls_session which failed.
1725 * @return
1726 * - UNLANG_ACTION_PUSHED_CHILD - the sections are running.
1727 * - UNLANG_ACTION_CALCULATE_RESULT - there is no `fail session` section, and
1728 * clearing the session pushed nothing.
1729 * - UNLANG_ACTION_FAIL - a frame could not be pushed.
1730 */
1731unlang_action_t fr_tls_session_fail_session(request_t *request, fr_tls_session_t *tls_session)
1732{
1733 fr_tls_conf_t *conf = tls_session->conf;
1734 request_t *child;
1735 unlang_action_t ua;
1736
1737 if (!conf->fail_session) return tls_session_fail_clear(request, tls_session);
1738
1740 NULL,
1741 tls_session_fail_clear,
1742 NULL, FR_SIGNAL_NONE, UNLANG_SUB_FRAME, tls_session) == UNLANG_ACTION_FAIL) {
1743 return UNLANG_ACTION_FAIL;
1744 }
1745
1746 /*
1747 * A session which failed before OpenSSL established one has
1748 * no ID to report, which tls_subrequest_alloc() handles.
1749 */
1750 MEM(child = tls_subrequest_alloc(request, enum_tls_packet_type_fail_session->vb_uint32,
1751 &tls_session->session_id));
1752
1753 ua = fr_tls_call_push(child, NULL, conf, tls_session, false);
1755 talloc_free(child);
1757 return UNLANG_ACTION_FAIL;
1758 }
1759
1760 return ua;
1761}
1762
1763/** Finish off a handshake round, possibly adding attributes to the request
1764 *
1765 */
1766static unlang_action_t tls_session_async_handshake_done_round(request_t *request, void *uctx)
1767{
1768 fr_tls_session_t *tls_session = talloc_get_type_abort(uctx, fr_tls_session_t);
1769
1770 RDEBUG3("(TLS) entered state %s", __FUNCTION__);
1771
1772 /*
1773 * This only occurs once per session, where calling
1774 * SSL_read updates the state of the SSL session, setting
1775 * this flag to true.
1776 *
1777 * Callbacks provide enough info so we don't need to
1778 * print debug statements when the handshake is in other
1779 * states.
1780 */
1781 if (SSL_is_init_finished(tls_session->ssl)) {
1782 SSL_CIPHER const *cipher;
1783 fr_pair_t *vp;
1784 char const *version;
1785
1786 char cipher_desc[256], cipher_desc_clean[256];
1787 char *p = cipher_desc, *q = cipher_desc_clean;
1788
1789 /*
1790 * Check if ALPN was successfully negotiated. We
1791 * can do this without caring about session
1792 * tickets.
1793 */
1794 if (fr_tls_session_alpn_check(request, tls_session) < 0) {
1795 fr_tls_session_close_send(request, tls_session);
1796 tls_session->result = FR_TLS_RESULT_ERROR;
1797 fr_tls_session_request_unbind(tls_session->ssl);
1799 }
1800
1801 cipher = SSL_get_current_cipher(tls_session->ssl);
1802 SSL_CIPHER_description(cipher, cipher_desc, sizeof(cipher_desc));
1803
1804 /*
1805 * Cleanup the output from OpenSSL
1806 * Seems to print info in a tabular format.
1807 */
1808 while (*p != '\0') {
1809 if (isspace((uint8_t) *p)) {
1810 p++;
1811 continue;
1812 }
1813 *q++ = *p++;
1814 }
1815 *q = '\0';
1816
1817 RDEBUG2("(TLS) Cipher suite: %s", cipher_desc_clean);
1818
1819 RDEBUG2("(TLS) Adding TLS session information to request");
1820 RINDENT();
1822 fr_pair_value_strdup(vp, SSL_CIPHER_get_name(cipher), false);
1823 RDEBUG2("(TLS) session-state.%pP", vp);
1824
1825 if (((size_t)tls_session->info.version >= NUM_ELEMENTS(tls_version_str)) ||
1826 !tls_version_str[tls_session->info.version]) {
1827 version = "UNKNOWN";
1828 } else {
1829 version = tls_version_str[tls_session->info.version];
1830 }
1831
1833 fr_pair_value_strdup(vp, version, false);
1834 RDEBUG2("(TLS) session-state.%pP", vp);
1835 REXDENT();
1836
1837 /*
1838 * Cache the SSL_SESSION pointer.
1839 *
1840 * Which contains all the data we need for session resumption.
1841 */
1842 if (!tls_session->session) {
1843 tls_session->session = SSL_get_session(tls_session->ssl);
1844 if (tls_session->session) {
1845 tls_session_id_cache(tls_session, tls_session->session);
1846 }
1847 if (!tls_session->session) {
1848 REDEBUG("(TLS) Failed getting TLS session");
1849 fr_tls_session_error_alert(request, tls_session,
1850 FR_ERROR_VALUE_SESSION_MISSING, SSL_AD_INTERNAL_ERROR);
1851 fr_tls_session_close_send(request, tls_session);
1852 tls_session->result = FR_TLS_RESULT_ERROR;
1853 fr_tls_session_request_unbind(tls_session->ssl);
1855 }
1856 }
1857
1858 if (RDEBUG_ENABLED3) {
1859 if (SSL_SESSION_print(fr_tls_request_log_bio(request, L_DBG, L_DBG_LVL_3),
1860 tls_session->session) != 1) {
1861 RDEBUG3("(TLS) Failed retrieving session data");
1862 }
1863 }
1864
1865 /*
1866 * Session was resumed, add attribute to mark it as such.
1867 */
1868 if (SSL_session_reused(tls_session->ssl)) {
1869 /*
1870 * Mark the request as resumed.
1871 */
1873 vp->vp_bool = true;
1874 }
1875 }
1876
1877 /*
1878 * Get the data to send to the peer. OpenSSL already did
1879 * it's magic, so we can just do ours here.
1880 *
1881 * No encrypted data means that OpenSSL produced no TLS
1882 * content, so the output is likely application data.
1883 */
1884 if (fr_dbuff_remaining(tls_session->dirty_out) == 0) {
1885 /* Its clean application data, do whatever we want */
1886 fr_tls_record_init(&tls_session->clean_out);
1887 }
1888
1889 /*
1890 * Trash the current data in dirty_out, and synthesize
1891 * a TLS error record.
1892 *
1893 * OpensSL annoyingly provides no mechanism for us to
1894 * send alerts, and we need to send alerts as part of
1895 * RFC 5216, so this is our only option.
1896 */
1897 if (tls_session->pending_alert) fr_tls_session_alert_send(request, tls_session);
1898
1899 tls_session->result = FR_TLS_RESULT_SUCCESS;
1900 fr_tls_session_request_unbind(tls_session->ssl);
1901 if (SSL_is_init_finished(tls_session->ssl)) {
1902 fr_tls_conf_t *conf = tls_session->conf;
1903 if (conf->establish_session) return tls_establish_session_push(request, conf, tls_session);
1904 }
1906}
1907
1908/** Try very hard to get the SSL * into a consistent state where it's not yielded
1909 *
1910 * ...because if it's yielded, we'll probably leak thread contexts and all kinds of memory.
1911 *
1912 * @param[in] request being cancelled.
1913 * @param[in] action we're being signalled with.
1914 * @param[in] uctx the SSL * to cancel.
1915 */
1916static void tls_session_async_handshake_signal(UNUSED request_t *request, UNUSED fr_signal_t action, void *uctx)
1917{
1918 fr_tls_session_t *tls_session = talloc_get_type_abort(uctx, fr_tls_session_t);
1919 int ret;
1920
1921 /*
1922 * We might want to set can_pause = false here
1923 * but that would trigger asserts in the
1924 * cache code.
1925 */
1926
1927 /*
1928 * If SSL_get_error returns SSL_ERROR_WANT_ASYNC
1929 * it means we're yielded in the middle of a
1930 * callback.
1931 *
1932 * Keep calling SSL_read() in a loop until we
1933 * no longer get SSL_ERROR_WANT_ASYNC, then
1934 * shut it down so it's in a consistent state.
1935 *
1936 * It'll get freed later when the request is
1937 * freed.
1938 */
1939 for (ret = tls_session->last_ret;
1940 SSL_get_error(tls_session->ssl, ret) == SSL_ERROR_WANT_ASYNC;
1941 ret = SSL_read(tls_session->ssl, fr_dbuff_current(&tls_session->clean_out),
1942 fr_dbuff_remaining(&tls_session->clean_out)));
1943
1944 /*
1945 * Unbind the cancelled request from the SSL *
1946 */
1947 fr_tls_session_request_unbind(tls_session->ssl);
1948}
1949
1950/** Push the section for one bit of #fr_tls_pending_t
1951 *
1952 */
1953typedef unlang_action_t (*fr_tls_pending_push_t)(request_t *request, fr_tls_session_t *tls_session);
1954
1955/** Push the section for every raised bit, then call SSL_read() to continue the TLS state machine
1956 *
1957 * This function may be called multiple times, once after every asynchronous request.
1958 *
1959 * @param[in] request The current request.
1960 * @param[in] uctx #fr_tls_session_t to continue.
1961 * @return
1962 * - UNLANG_ACTION_CALCULATE_RESULT - We're done with this round, or a push
1963 * failed and `tls_session->result` is FR_TLS_RESULT_ERROR.
1964 * - UNLANG_ACTION_PUSHED_CHILD - Need to perform more asynchronous actions.
1965 */
1966static unlang_action_t tls_session_async_handshake_cont(request_t *request, void *uctx)
1967{
1968 /*
1969 * `push[idx]` is the push function for bit `1 << idx`.
1970 */
1971 static fr_tls_pending_push_t const push[] = {
1972 [0] = fr_tls_ticket_stateful_pending_push, /* FR_TLS_PENDING_STATEFUL_TICKET */
1973 [1] = fr_tls_ticket_stateless_pending_push, /* FR_TLS_PENDING_STATELESS_TICKET */
1974#ifdef PSK_MAX_IDENTITY_LEN
1975 [2] = fr_tls_session_psk_pending_push, /* FR_TLS_PENDING_PSK */
1976#endif
1977 [3] = fr_tls_verify_cert_pending_push, /* FR_TLS_PENDING_VERIFY */
1978 };
1979 fr_tls_session_t *tls_session = talloc_get_type_abort(uctx, fr_tls_session_t);
1980 int err;
1981
1982 RDEBUG3("(TLS) (re-)entered state %s", __FUNCTION__);
1983
1984again:
1985 while (tls_session->pending) {
1986 unsigned int idx = fr_low_bit_pos(tls_session->pending) - 1;
1987 fr_tls_pending_t bit = (fr_tls_pending_t)(UINT64_C(1) << idx);
1988 unlang_action_t ua;
1989
1990 fr_assert(idx < NUM_ELEMENTS(push));
1991 fr_assert(push[idx]);
1992
1993 /*
1994 * Each bit is one shot. The push function is called once for
1995 * the bit, and raises the bit again if the callback asks again.
1996 */
1997 TLS_PENDING_CLEAR(tls_session, bit);
1998
1999 /*
2000 * Set this function as the repeat function before the push, so
2001 * the frame runs this function again once the section has finished.
2002 */
2003 if (unlikely(unlang_function_repeat_set(request, tls_session_async_handshake_cont) < 0)) {
2004 error:
2005 tls_session->result = FR_TLS_RESULT_ERROR;
2006 goto finish;
2007 }
2008
2009 ua = push[idx](request, tls_session);
2010 switch (ua) {
2012 return ua;
2013
2014 case UNLANG_ACTION_FAIL:
2016 goto error;
2017
2018 default:
2019 /*
2020 * The push function found nothing to push for this bit, so the
2021 * repeat function never runs. Clear the repeat function and
2022 * service the next raised bit.
2023 */
2025 break;
2026 }
2027 }
2028
2029 /*
2030 * Clear OpenSSL's thread local error stack.
2031 *
2032 * Why do we need to do this here? Although SSL_get_error
2033 * takes an `SSL *`, which would make you _think_ it was
2034 * operating on the error stack for that SSL, it will also
2035 * return SSL_ERROR_SSL if there are any errors in the stack.
2036 *
2037 * When operating normally SSL_read() can return < 0, to
2038 * indicate it wants more data, or that we need to perform
2039 * asynchronous processing.
2040 *
2041 * If spurious errors have been left on the thread local
2042 * stack they MUST be cleared before we can call SSL_get_error
2043 * otherwise stale errors mask the async notifications
2044 * and cause random handshake failures.
2045 */
2046 ERR_clear_error();
2047
2048 /*
2049 * Magic/More magic? Although SSL_read is normally
2050 * used to read application data, it will also
2051 * continue the TLS handshake. Removing this call will
2052 * cause the handshake to fail.
2053 *
2054 * We don't ever expect to actually *receive* application
2055 * data here.
2056 *
2057 * The reason why we call SSL_read instead of SSL_accept,
2058 * or SSL_connect, as it allows this function
2059 * to be used, irrespective or whether we're acting
2060 * as a client or a server.
2061 *
2062 * If acting as a client SSL_set_connect_state must have
2063 * been called before this function.
2064 *
2065 * If acting as a server SSL_set_accept_state must have
2066 * been called before this function.
2067 */
2068 tls_session->can_pause = true;
2069 tls_session->last_ret = SSL_read(tls_session->ssl, fr_dbuff_current(&tls_session->clean_out),
2070 fr_dbuff_remaining(&tls_session->clean_out));
2071 tls_session->can_pause = false;
2072 if (tls_session->last_ret > 0) {
2073 fr_dbuff_advance(&tls_session->clean_out, (size_t) tls_session->last_ret);
2074
2075 /*
2076 * We've received application data. This is a positive
2077 * signal that all session tickets have been sent.
2078 * This flag informs fr_tls_session_is_init_finished().
2079 */
2080 tls_session->seen_application_data = true;
2081
2082 /*
2083 * Round successful, and we don't need to do any
2084 * further processing.
2085 */
2086 tls_session->result = FR_TLS_RESULT_SUCCESS;
2087 finish:
2088 /*
2089 * Was bound by caller
2090 */
2091 fr_tls_session_request_unbind(tls_session->ssl);
2093 }
2094
2095 /*
2096 * Bug in OpenSSL 3.0 - Normal handshaking behaviour
2097 * results in spurious "BIO_R_UNSUPPORTED_METHOD"
2098 * errors.
2099 *
2100 * SSL_get_error apparently returns SSL_ERROR_SSL if
2101 * there are any errors in the stack. This masks
2102 * SSL_ERROR_WANT_ASYNC and causes the handshake to
2103 * fail.
2104 *
2105 * Note: We may want some version of this code
2106 * included for all OpenSSL versions.
2107 *
2108 * It would call ERR_GET_FATAL() on each of the errors
2109 * in the stack to drain non-fatal errors and prevent
2110 * the other (more useful) return codes of
2111 * SSL_get_error from being masked. I guess we'll see
2112 * if this occurs in other scenarios.
2113 */
2114 if (SSL_get_error(tls_session->ssl, tls_session->last_ret) == SSL_ERROR_SSL) {
2115 unsigned long ssl_err;
2116
2117 /*
2118 * Some weird OpenSSL thing marking ERR_GET_REASON
2119 * as "unused". Unclear why this is done as it's
2120 * not deprecated.
2121 */
2122DIAG_OFF_OPTIONAL(used-but-marked-unused)
2123 while ((ssl_err = ERR_peek_error()) && (ERR_GET_REASON(ssl_err) == BIO_R_UNSUPPORTED_METHOD)) {
2124 (void) ERR_get_error();
2125 }
2126DIAG_ON_OPTIONAL(used-but-marked-unused)
2127 }
2128
2129 /*
2130 * Deal with asynchronous requests from OpenSSL.
2131 * These aren't actually errors, they're the
2132 * result of one of our callbacks indicating that
2133 * it'd like to perform the operation
2134 * asynchronously.
2135 */
2136 switch (err = SSL_get_error(tls_session->ssl, tls_session->last_ret)) {
2137 case SSL_ERROR_WANT_ASYNC: /* Certification validation or cache loads */
2138 goto again;
2139
2140 case SSL_ERROR_WANT_ASYNC_JOB:
2141 REDEBUG("(TLS) No async jobs available in pool, increase thread.openssl_async_pool_max");
2142 goto error;
2143
2144 default:
2145 /*
2146 * Returns 0 if we can continue processing the handshake
2147 * Returns -1 if we encountered a fatal error.
2148 */
2149 if (fr_tls_log_io_error(request,
2150 err, "SSL_read (%s)", __FUNCTION__) < 0) goto error;
2151 return tls_session_async_handshake_done_round(request, uctx);
2152 }
2153}
2154
2155/** Ingest data for another handshake round
2156 *
2157 * Advance the TLS handshake by feeding OpenSSL data from dirty_in,
2158 * and reading data from OpenSSL into dirty_out.
2159 *
2160 * Calls #tls_session_async_handshake_read to perform the actual ingestion.
2161 * #tls_session_async_handshake_read is split out because we may need to call
2162 * it multiple times, once after every async action.
2163 *
2164 * @param[in] request The current request.
2165 * @param[in] uctx #fr_tls_session_t to continue.
2166 * @return
2167 * - UNLANG_ACTION_CALCULATE_RESULT - We're done with this round.
2168 * - UNLANG_ACTION_PUSHED_CHILD - Need to perform more asynchronous actions.
2169 */
2170static unlang_action_t tls_session_handshake_round(request_t *request, void *uctx)
2171{
2172 fr_tls_session_t *tls_session = talloc_get_type_abort(uctx, fr_tls_session_t);
2173
2174 RDEBUG3("(TLS) entered state %s", __FUNCTION__);
2175
2176 tls_session->result = FR_TLS_RESULT_IN_PROGRESS;
2177
2178 fr_tls_session_request_bind(tls_session->ssl, request); /* May be unbound in this function or asynchronously */
2179
2180 /*
2181 * This is a logic error.
2182 * fr_tls_session_async_handshake() must not be called if
2183 * the handshake is complete. fr_tls_session_recv() must
2184 * be called instead.
2185 *
2186 * Check for full init finished, including TLS 1.3 for a
2187 * client with stateless session tickets. Those arrive
2188 * after the TLS handshake has completed.
2189 */
2190 if (fr_tls_session_is_init_finished(tls_session)) {
2191 REDEBUG("(TLS) Attempted to continue TLS handshake, but handshake has completed");
2192 fr_tls_session_error_alert(request, tls_session,
2193 FR_ERROR_VALUE_HANDSHAKE_FINISHED, SSL_AD_INTERNAL_ERROR);
2194 error:
2195 /*
2196 * The end of the round is what normally sends a
2197 * queued alert, and this exit does not reach it.
2198 * EAP has no other chance: it pushes the handshake
2199 * itself and never touches fr_tls_connection_t.
2200 */
2201 fr_tls_session_close_send(request, tls_session);
2202 tls_session->result = FR_TLS_RESULT_ERROR;
2203 fr_tls_session_request_unbind(tls_session->ssl); /* Was bound in this function */
2205 }
2206
2207 if (tls_session->invalid) {
2208 REDEBUG("(TLS) Preventing invalid session from continuing");
2209 fr_tls_session_error_alert(request, tls_session,
2210 FR_ERROR_VALUE_SESSION_INVALID, SSL_AD_INTERNAL_ERROR);
2211 goto error;
2212 }
2213
2214 /*
2215 * This function runs once per handshake message, and
2216 * only for handshake messages. Count the number of
2217 * handshakes, and if there are too many, then forcibly
2218 * stop the TLS negotiation.
2219 */
2220 tls_session->rounds++;
2221 if (tls_session->rounds >= FR_TLS_MAX_ROUNDS) {
2222 REDEBUG("(TLS) Failing TLS session due to too many handshake rounds (limit %u)", FR_TLS_MAX_ROUNDS);
2223 fr_tls_session_error_alert(request, tls_session,
2224 FR_ERROR_VALUE_TOO_MANY_ROUNDS, SSL_AD_INTERNAL_ERROR);
2225 goto error;
2226 }
2227
2228 /*
2229 * OpenSSL does it's magic to convert the encrypted
2230 * dirty_in data to clean_out application data.
2231 */
2232 return tls_session_async_handshake_cont(request, uctx); /* Must unbind request, possibly asynchronously */
2233}
2234
2235/** Ask the virtual server for a session to resume, then start the handshake
2236 *
2237 * Only a client picks a session to resume before the handshake starts. A
2238 * server is asked for one by OpenSSL, part way through the handshake, and
2239 * answers from tls_ticket_stateful_load_cb().
2240 *
2241 * Nothing is bound to the SSL * yet, so the `load session { ... }` section can
2242 * push a subrequest without the handshake holding the SSL * while that
2243 * subrequest runs.
2244 */
2245static unlang_action_t tls_session_load_session(request_t *request, void *uctx)
2246{
2247 fr_tls_session_t *tls_session = talloc_get_type_abort(uctx, fr_tls_session_t);
2248 unlang_action_t ua;
2249
2250 /*
2251 * The round runs next whatever happens here, so arm it before
2252 * pushing anything. unlang_function_repeat_set() only works
2253 * while this frame is on top of the stack, and pushing a child
2254 * puts another frame on top.
2255 */
2256 if (unlikely(unlang_function_repeat_set(request, tls_session_handshake_round) < 0)) {
2257 error:
2258 tls_session->result = FR_TLS_RESULT_ERROR;
2260 }
2261
2262 ua = fr_tls_ticket_stateful_load_client_push(request, tls_session);
2263 if (ua == UNLANG_ACTION_PUSHED_CHILD) return ua;
2264 if (ua == UNLANG_ACTION_FAIL) goto error;
2265
2266 return tls_session_handshake_round(request, uctx);
2267}
2268
2269/** Run one round of the handshake, and the policy which precedes the first one
2270 *
2271 * The caller pushes this once per round, so the work which happens only once
2272 * is keyed off the round counter. `tls_session->rounds` is incremented by
2273 * tls_session_handshake_round(), so a zero here means no round has run yet.
2274 *
2275 * `new session { ... }` is not run here. That section runs before the
2276 * session is allocated, so that it can set control attributes which decide how
2277 * the session is allocated, such as EAP-TLS-Require-Client-Cert. By the time
2278 * a handshake round runs, the session already exists and the decision has been
2279 * taken. Running `new session { ... }` from here would be too late, so the
2280 * caller runs it.
2281 */
2282static unlang_action_t tls_session_async_handshake(request_t *request, void *uctx)
2283{
2284 fr_tls_session_t *tls_session = talloc_get_type_abort(uctx, fr_tls_session_t);
2285
2286 if ((tls_session->rounds == 0) && !SSL_is_server(tls_session->ssl)) {
2287 return tls_session_load_session(request, uctx);
2288 }
2289
2290 return tls_session_handshake_round(request, uctx);
2291}
2292
2293/** Push a handshake call onto the stack
2294 *
2295 * We push the handshake frame (as opposed to having the caller do it),
2296 * so that we guarantee there's a frame that the handshake function can
2297 * manipulate to manage its own state.
2298 *
2299 * The result of processing this handshake round can be found in
2300 * tls_session->result.
2301 *
2302 * @param[in] request The current request.
2303 * @param[in] tls_session to continue handshaking.
2304 * @return
2305 * - UNLANG_ACTION_PUSHED_CHILD on success.
2306 * - UNLANG_ACTION_FAIL on failure.
2307 */
2308unlang_action_t fr_tls_session_async_handshake_push(request_t *request, fr_tls_session_t *tls_session)
2309{
2311 tls_session_async_handshake,
2312 NULL,
2313 tls_session_async_handshake_signal,
2316 tls_session);
2317}
2318
2319/** Callback run during ClientHello phase of handshake
2320 *
2321 * The SSL_client_hello* functions can only be called inside a callback like this.
2322 */
2323static int fr_tls_session_client_hello_cb(SSL *ssl, UNUSED int *al, UNUSED void *arg)
2324{
2325 fr_tls_conf_t *conf = fr_tls_session_conf(ssl);
2326 request_t *request = SSL_get_ex_data(ssl, FR_TLS_EX_INDEX_REQUEST);
2327
2328 /*
2329 * Is there a session_ticket extension in the CLientHello?
2330 * If not, the client doesn't support session tickets - disable them.
2331 */
2332 if (conf->cache.mode != FR_TLS_TICKET_DISABLED) {
2333 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_session_ticket, NULL, NULL) == 1) {
2334 fr_tls_session_t *tls_session = fr_tls_session(ssl);
2335 tls_session->session_ticket_supported = true;
2336 } else {
2337 long ssl_options = SSL_get_options(ssl);
2338 RDEBUG2("(TLS) Session ticket extension not found in ClientHello");
2339 ssl_options |= SSL_OP_NO_TICKET;
2340 SSL_set_options(ssl, ssl_options);
2341 }
2342 }
2343
2344 if (conf->client_hello_parse) return fr_tls_session_client_hello_pairs(ssl, request);
2345
2346 return SSL_CLIENT_HELLO_SUCCESS;
2347}
2348
2349/** Free a TLS session and any associated OpenSSL data
2350 *
2351 * @param session to free.
2352 * @return 0.
2353 */
2354static int _fr_tls_session_free(fr_tls_session_t *session)
2355{
2356 /*
2357 * Ensure that there are no pending cache operations
2358 * before we free the session. Leaving a pending cache
2359 * operation might mean that the session ticket isn't
2360 * cleared, and the TLS peer can then use it to resume
2361 * the session.
2362 */
2363 fr_assert_msg(!fr_tls_ticket_stateful_pending(session->cache),
2364 "Session freed with cache work outstanding, the caller called neither "
2365 "fr_tls_ticket_stateful_store_session() nor fr_tls_ticket_stateful_clear_session()");
2366
2367 if (session->ssl) {
2368 /*
2369 * The OpenSSL docs state:
2370 *
2371 * SSL_shutdown() can be modified to only set the
2372 * connection to "shutdown" state but not actually
2373 * send the "close notify" alert messages, see
2374 * SSL_CTX_set_quiet_shutdown(3). When "quiet shutdown"
2375 * is enabled, SSL_shutdown() will always succeed and
2376 * return 1.
2377 *
2378 * This is only partially correct. This call does mean
2379 * we don't notify the other party, but the SSL_shutdown
2380 * call can still fail if the handshake hasn't begun, leaving
2381 * spurious errors on the thread local error stack.
2382 */
2383 SSL_set_quiet_shutdown(session->ssl, 1);
2384
2385 /*
2386 * Don't leave spurious errors raised by SSL_shutdown on
2387 * the error stack.
2388 */
2389 if (SSL_shutdown(session->ssl) != 1) ERR_clear_error();
2390
2391 SSL_free(session->ssl);
2392 session->ssl = NULL;
2393 }
2394
2395 return 0;
2396}
2397
2398/** Allocate a new #fr_tls_session_t and initialize it
2399 *
2400 */
2401static fr_tls_session_t *tls_session_alloc(TALLOC_CTX *ctx, request_t *request, SSL_CTX *ssl_ctx)
2402{
2403 fr_tls_session_t *tls_session;
2404
2405 tls_session = talloc_zero(ctx, fr_tls_session_t);
2406 if (!tls_session) return NULL;
2407
2408 /*
2409 * The socket type determines whether we use TLS or DTLS.
2410 */
2411 tls_session->socket_type = (SSL_CTX_get_ssl_method(ssl_ctx) == DTLS_method()) ? SOCK_DGRAM : SOCK_STREAM;
2412
2413 /*
2414 * Cache the configuration pointer, because it doesn't change during the lifetime of the
2415 * connection.
2416 */
2417 tls_session->conf = fr_tls_ctx_conf(ssl_ctx);
2418
2419 tls_session->ctx = ssl_ctx;
2420
2421 tls_session->ssl = SSL_new(ssl_ctx);
2422 if (!tls_session->ssl) {
2423 talloc_free(tls_session);
2424 fr_tls_log_perror(request, "Error creating new TLS session");
2425 return NULL;
2426 }
2427
2428 talloc_set_destructor(tls_session, _fr_tls_session_free);
2429 fr_pair_list_init(&tls_session->extra_pairs);
2430
2431 fr_value_box_init_null(&tls_session->session_id);
2432
2433 /*
2434 * Add the message callback to identify what type of
2435 * message/handshake is passed
2436 */
2437 SSL_set_msg_callback(tls_session->ssl, fr_tls_session_msg_cb);
2438 SSL_set_msg_callback_arg(tls_session->ssl, tls_session);
2439 SSL_set_info_callback(tls_session->ssl, fr_tls_session_info_cb);
2440
2441 SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_TLS_SESSION, (void *)tls_session);
2442
2443 /*
2444 * The client sometimes doesn't have a request. The server always has one.
2445 */
2446 if (!request) return tls_session;
2447
2448 /*
2449 * If there is a request, then allocate the record buffers and
2450 * create the BIOs. Otherwise leave the record buffers empty and
2451 * the bio handles as NULL, so that any accidental use
2452 * causes problems.
2453 */
2454 {
2455 fr_dbuff_t *record[] = { &tls_session->clean_in, &tls_session->clean_out };
2456 size_t i;
2457
2458 for (i = 0; i < NUM_ELEMENTS(record); i++) {
2459 uint8_t *buff;
2460
2461 MEM(buff = talloc_array(tls_session, uint8_t, SSL3_RT_MAX_PLAIN_LENGTH));
2462 fr_dbuff_init(record[i], buff, (size_t) SSL3_RT_MAX_PLAIN_LENGTH);
2463 }
2464 }
2465
2466 /*
2467 * Create & hook the BIOs to handle the dirty side of the
2468 * SSL. The caller writes encrypted data into the
2469 * "dirty_in" side via some external mechanism, and
2470 * writes encrypted data out of the "dirty_out" side via
2471 * an external mechanism. This design allows us to use
2472 * the same TLS code for both RadSec, and for all
2473 * TLS-enabled EAP methods.
2474 *
2475 * OpenSSL either reads "dirty_in" and writes
2476 * "clean_out", or reads "clean_in" and writes
2477 * "dirty_out".
2478 *
2479 * We allocate a fixed size buffer going into_ssl,
2480 * because an extensible buffer could allow the peer to
2481 * send us unbounded data. A fixed size buffer allows
2482 * this code to limit that usage.
2483 *
2484 * @todo - make the input buffer extendable, but with
2485 * a maximum limit, and only after all TLS negotiation
2486 * has completed, and the session is fully authenticated.
2487 *
2488 * The size is FR_TLS_MAX_PACKET_SIZE and not
2489 * SSL3_RT_MAX_PLAIN_LENGTH. Data OpenSSL has not used
2490 * stay in the buffer, as they are generally partial TLS
2491 * records. But the buffer has to be large enough to
2492 * hold an entire TLS record.
2493 *
2494 * init and max are the same, so the buffer is allocated
2495 * once and never moves.
2496 *
2497 * We don't limit the data coming out of from_ssl,
2498 * because OpenSSL decides how much it writes. Multiple
2499 * handshakes could carry a long certificate chain, which
2500 * exceeds one record in size.
2501 */
2502 {
2503 BIO *rbio, *wbio;
2504
2505 /*
2506 * free_buff is false because tls_session is the talloc
2507 * parent of the buffer as well as of the
2508 * fr_tls_bio_dbuff_t. talloc frees the buffer with the
2509 * session, and a destructor which freed it too would
2510 * free it twice.
2511 */
2512 MEM(rbio = fr_tls_bio_dbuff_alloc(&tls_session->into_ssl, tls_session, tls_session,
2513 FR_TLS_MAX_PACKET_SIZE, FR_TLS_MAX_PACKET_SIZE, false));
2514 MEM(wbio = fr_tls_bio_dbuff_alloc(&tls_session->from_ssl, tls_session, tls_session,
2515 SSL3_RT_MAX_PLAIN_LENGTH, 0, false));
2516
2517 tls_session->dirty_in = fr_tls_bio_dbuff_in(tls_session->into_ssl);
2518 tls_session->dirty_out = fr_tls_bio_dbuff_out(tls_session->from_ssl);
2519
2520 /*
2521 * SSL_set_bio() takes ownership of both BIOs, and the
2522 * fr_tls_bio_dbuff_t destructor frees its own BIO. Give
2523 * each owner a reference to drop.
2524 */
2525 BIO_up_ref(rbio);
2526 BIO_up_ref(wbio);
2527 SSL_set_bio(tls_session->ssl, rbio, wbio);
2528 }
2529
2530 return tls_session;
2531}
2532
2533/** Create a new client TLS session
2534 *
2535 * Configures a new client TLS session, configuring options, setting callbacks etc...
2536 *
2537 * If request is not passed, the caller gets a bare SSL*, and owns
2538 * the transport itself. The session has no memory BIOs, and OpenSSL
2539 * does the certificate validation on its own. This API is used by
2540 * hiredis, which needs direct access to the bare SSL*
2541 *
2542 * If a request is passed, the session management follows the server
2543 * session path. Data goes through memory BIOs,
2544 * fr_tls_session_async_handshake_push() is run for each round, and
2545 * certificate verification calls the `verify certificate` section of
2546 * the configured virtual_server.
2547 *
2548 * @param[in] ctx to alloc session data in. Should usually be NULL unless the lifetime of the
2549 * session is tied to another talloc'd object.
2550 * @param[in] ssl_ctx containing the base configuration for this session.
2551 * @param[in] request which the handshake runs under, or NULL for a session whose transport
2552 * is owned by the caller.
2553 * @return
2554 * - A new session on success.
2555 * - NULL on error.
2556 */
2557fr_tls_session_t *fr_tls_session_alloc_client(TALLOC_CTX *ctx, SSL_CTX *ssl_ctx, request_t *request)
2558{
2559 int verify_mode;
2560 fr_tls_session_t *tls_session;
2561 fr_tls_conf_t *conf = fr_tls_ctx_conf(ssl_ctx);
2562
2563 tls_session = tls_session_alloc(ctx, request, ssl_ctx);
2564 if (!tls_session) return NULL;
2565
2566 /*
2567 * In Client mode we only connect.
2568 *
2569 * This sets up the SSL session to work correctly with
2570 * fr_tls_session_handshake.
2571 */
2572 SSL_set_connect_state(tls_session->ssl);
2573
2574 /*
2575 * Always verify the peer, but only require a certificate
2576 * when we're doing certificate authentication.
2577 *
2578 * PSK doesn't use certs, so we can't require certs if
2579 * we're using PSK.
2580 */
2581 verify_mode = SSL_VERIFY_PEER;
2582 if (!conf->psk.identity) {
2583 ROPTIONAL(RDEBUG2, DEBUG2, "Requiring Server certificate");
2584 verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
2585 }
2586
2587 if (request) {
2588 /*
2589 * fr_tls_verify_cert_cb() pauses the handshake and runs
2590 * the `verify certificate` section. It needs a request,
2591 * and it needs to be called from inside
2592 * tls_session_async_handshake_cont().
2593 */
2594 tls_session->verify_peer_cert = true;
2595 SSL_set_verify(tls_session->ssl, verify_mode, fr_tls_verify_cert_cb);
2596 } else {
2597 /*
2598 * With no request there is nowhere to run a policy, so
2599 * OpenSSL does the validating. When the callback is
2600 * NULL OpenSSL uses its own validation function, and the
2601 * flags modify that function's behaviour.
2602 */
2603 SSL_set_verify(tls_session->ssl, verify_mode, NULL);
2604 }
2605
2606 SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_CONF, (void *)conf);
2607
2608 /*
2609 * Datagrams need to be limited to a pre-configured MTU. So we remember that, and tell OpenSSL
2610 * to limit the MTU.
2611 */
2612 if ((tls_session->socket_type == SOCK_DGRAM) && (fr_dtls_session_init(tls_session, conf) < 0)) {
2613 talloc_free(tls_session);
2614 return NULL;
2615 }
2616
2617 /*
2618 * Session resumption needs somewhere to keep its state, and is
2619 * driven by the caller. See fr_tls_ticket_stateful_load_client_push() and
2620 * fr_tls_ticket_stateful_pending_push().
2621 */
2622 if (request && (conf->cache.mode != FR_TLS_TICKET_DISABLED)) {
2623 tls_session->allow_session_resumption = true; /* otherwise it's false */
2624 fr_tls_ticket_stateful_session_alloc(tls_session);
2625 }
2626
2627 return tls_session;
2628}
2629
2630/** Create a new server TLS session
2631 *
2632 * Configures a new server TLS session, configuring options, setting callbacks etc...
2633 *
2634 * @param[in] ctx to alloc session data in. Should usually be NULL
2635 * unless the lifetime of the session is tied to another
2636 * talloc'd object.
2637 * @param[in] ssl_ctx containing the base configuration for this session.
2638 * @param[in] request The current #request_t.
2639 * @param[in] client_cert Whether to require a client_cert.
2640 * @return
2641 * - A new session on success.
2642 * - NULL on error.
2643 */
2644fr_tls_session_t *fr_tls_session_alloc_server(TALLOC_CTX *ctx, SSL_CTX *ssl_ctx, request_t *request, bool client_cert)
2645{
2646 fr_tls_session_t *tls_session;
2647 int verify_mode = 0;
2648 fr_pair_t *vp;
2649 fr_tls_conf_t *conf = fr_tls_ctx_conf(ssl_ctx);
2650
2651 RDEBUG2("(TLS) Initiating new TLS session");
2652
2653 tls_session = tls_session_alloc(ctx, request, ssl_ctx);
2654 if (!tls_session) return NULL;
2655
2656 fr_tls_session_request_bind(tls_session->ssl, request); /* Is unbound in this function */
2657
2658 /*
2659 * This sets the context sessions can be resumed in.
2660 * This is to prevent sessions being created by one application
2661 * and used by another. In our case it prevents sessions being
2662 * reused between modules, or TLS server components such as
2663 * RADSEC.
2664 *
2665 * A context must always be set when doing session resumption
2666 * otherwise session resumption will fail.
2667 *
2668 * As the context ID must be <= 32, we digest the context
2669 * data with sha256.
2670 *
2671 * This seems to only be used for stateful session resumption
2672 * not session-tickets
2673 */
2674 if (conf->cache.mode != FR_TLS_TICKET_DISABLED) {
2675 char *context_id;
2676 EVP_MD_CTX *md_ctx;
2677 uint8_t digest[SHA256_DIGEST_LENGTH];
2678
2679 static_assert(sizeof(digest) <= SSL_MAX_SSL_SESSION_ID_LENGTH,
2680 "SSL_MAX_SSL_SESSION_ID_LENGTH must be >= SHA256_DIGEST_LENGTH");
2681 fr_assert(conf->cache.id_name);
2682
2683 if (tmpl_aexpand(tls_session, &context_id, request, conf->cache.id_name, NULL, NULL) < 0) {
2684 RPEDEBUG("(TLS) Failed expanding session ID");
2685 error:
2686 fr_tls_session_request_unbind(tls_session->ssl); /* Was bound in this function */
2687 talloc_free(tls_session);
2688 return NULL;
2689 }
2690
2691 MEM(md_ctx = EVP_MD_CTX_create());
2692 EVP_DigestInit_ex(md_ctx, EVP_sha256(), NULL);
2693 EVP_DigestUpdate(md_ctx, context_id, talloc_strlen(context_id));
2694 EVP_DigestFinal_ex(md_ctx, digest, NULL);
2695 EVP_MD_CTX_destroy(md_ctx);
2696 talloc_free(context_id);
2697
2698 if (!fr_cond_assert(SSL_set_session_id_context(tls_session->ssl,
2699 digest, sizeof(digest)) == 1)) goto error;
2700 }
2701
2702 /*
2703 * Add the session certificate to the session.
2704 */
2705 vp = fr_pair_find_by_da(&request->control_pairs, NULL, attr_tls_session_cert_file);
2706 if (vp) {
2707 RDEBUG2("(TLS) Loading TLS session certificate \"%pV\"", &vp->data);
2708
2709 if (SSL_use_certificate_file(tls_session->ssl, vp->vp_strvalue, SSL_FILETYPE_PEM) != 1) {
2710 fr_tls_log_perror(request, "Failed loading TLS session certificate \"%s\"",
2711 vp->vp_strvalue);
2712 goto error;
2713 }
2714
2715 if (SSL_use_PrivateKey_file(tls_session->ssl, vp->vp_strvalue, SSL_FILETYPE_PEM) != 1) {
2716 fr_tls_log_perror(request, "Failed loading TLS session certificate \"%s\"",
2717 vp->vp_strvalue);
2718 goto error;
2719 }
2720
2721 if (SSL_check_private_key(tls_session->ssl) != 1) {
2722 fr_tls_log_perror(request, "Failed validating TLS session certificate \"%s\"",
2723 vp->vp_strvalue);
2724 goto error;
2725 }
2726 /*
2727 * Better to perform explicit checks, than rely
2728 * on OpenSSL's opaque error messages.
2729 */
2730 } else {
2731 if (!conf->chains || !conf->chains[0]->private_key_file) {
2732 REDEBUG("(TLS) Server requires a private key file");
2733 fr_tls_session_error_add(request, FR_ERROR_VALUE_NO_SERVER_PRIVATE_KEY);
2734 goto error;
2735 }
2736
2737 if (!conf->chains || !conf->chains[0]->certificate_file) {
2738 REDEBUG("(TLS) Server requires a certificate file");
2739 fr_tls_session_error_add(request, FR_ERROR_VALUE_NO_SERVER_CERTIFICATE);
2740 goto error;
2741 }
2742 }
2743
2744 /** Dynamic toggle for allowing disallowing client certs
2745 *
2746 * This is mainly used for testing in environments where we can't
2747 * get test credentials for the host.
2748 */
2750 if (vp) client_cert = vp->vp_bool;
2751
2752 /*
2753 * In Server mode we only accept.
2754 *
2755 * This sets up the SSL session to work correctly with
2756 * fr_tls_session_handshake.
2757 */
2758 SSL_set_accept_state(tls_session->ssl);
2759
2760 /*
2761 * Verify the peer certificate, if asked.
2762 */
2763 if (client_cert) {
2764 RDEBUG2("(TLS) Setting verify mode to require certificate from client");
2765 verify_mode = SSL_VERIFY_PEER;
2766 verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
2767 verify_mode |= SSL_VERIFY_CLIENT_ONCE;
2768 }
2769 tls_session->verify_peer_cert = client_cert;
2770
2771 SSL_set_verify(tls_session->ssl, verify_mode, fr_tls_verify_cert_cb);
2772 SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_CONF, (void *)conf);
2773
2774 /*
2775 * Datagrams need to be limited to a pre-configured MTU. So we remember that, and tell OpenSSL
2776 * to limit the MTU.
2777 */
2778 if ((tls_session->socket_type == SOCK_DGRAM) && (fr_dtls_session_init(tls_session, conf) < 0)) {
2779 goto error;
2780 }
2781
2782 SSL_CTX_set_client_hello_cb(ssl_ctx, fr_tls_session_client_hello_cb, NULL);
2783
2784 if (conf->cache.mode != FR_TLS_TICKET_DISABLED) {
2785 tls_session->allow_session_resumption = true; /* otherwise it's false */
2786 if (conf->cache.mode & FR_TLS_TICKET_STATEFUL) fr_tls_ticket_stateful_session_alloc(tls_session);
2787 }
2788
2789 fr_tls_session_request_unbind(tls_session->ssl); /* Was bound in this function */
2790
2791 return tls_session;
2792}
2793
2794static unlang_action_t tls_new_session_result(request_t *request, UNUSED void *uctx)
2795{
2796 request_t *parent = request->parent;
2797
2799
2800 /*
2801 * Copy control attributes back to the parent.
2802 */
2803 if (fr_pair_list_copy(parent->control_ctx, &parent->control_pairs, &request->control_pairs) < 0) return UNLANG_ACTION_FAIL;
2804
2806}
2807
2808unlang_action_t fr_tls_new_session_push(request_t *request, fr_tls_conf_t const *tls_conf)
2809{
2810 request_t *child;
2811 fr_value_box_t id;
2812
2813 /*
2814 * There is no session yet, so there is no ID to report.
2815 */
2817
2818 MEM(child = tls_subrequest_alloc(request, enum_tls_packet_type_new_session->vb_uint32, &id));
2819
2820 if (unlang_subrequest_child_push(NULL, child, request, true, UNLANG_SUB_FRAME) < 0) {
2821 /*
2822 * The child hasn't run, so we shouldn't call
2823 * unlang_subrequest_detach_and_free().
2824 */
2826 talloc_free(child);
2827 return UNLANG_ACTION_FAIL;
2828 }
2829
2831 NULL,
2832 tls_new_session_result,
2833 NULL, FR_SIGNAL_NONE,
2835 /*
2836 * We just pushed the child frame onto the stack.
2837 * We don't want the subrequest to execute, if we then
2838 * failed to push the function that executes after it
2839 * returns.
2840 */
2841 error:
2844 talloc_free(child);
2845 return UNLANG_ACTION_FAIL;
2846 }
2847
2848 /*
2849 * unlang_call_push() fails when the virtual server was never
2850 * compiled, not only when memory runs out. So this is a
2851 * configuration error, and is reachable.
2852 */
2853 if (unlang_call_push(NULL, child, tls_conf->virtual_server, UNLANG_SUB_FRAME) < 0) goto error;
2854
2856}
2857#endif /* WITH_TLS */
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition action.h:35
@ UNLANG_ACTION_PUSHED_CHILD
unlang_t pushed a new child onto the stack, execute it instead of continuing.
Definition action.h:40
@ UNLANG_ACTION_FAIL
Encountered an unexpected error.
Definition action.h:36
@ UNLANG_ACTION_CALCULATE_RESULT
Calculate a new section rlm_rcode_t value.
Definition action.h:38
static int const char char buffer[256]
Definition acutest.h:641
void int line
Definition acutest.h:810
static uint8_t request[4]
#define IGNORE(_expr, _type)
Definition build.h:627
#define DIAG_OFF_OPTIONAL(_x)
Definition build.h:577
#define unlikely(_x)
Definition build.h:486
#define UNUSED
Definition build.h:415
#define NUM_ELEMENTS(_t)
Definition build.h:437
#define DIAG_ON_OPTIONAL(_x)
Definition build.h:578
unlang_action_t unlang_call_push(unlang_result_t *p_result, request_t *request, CONF_SECTION *server_cs, bool top_frame)
Push a virtual server CONF_SECTION as a call frame onto the stack.
Definition call.c:151
#define fr_dbuff_advance(_dbuff_or_marker, _len)
Advance 'current' position in dbuff or marker by _len bytes.
Definition dbuff.h:1121
#define fr_dbuff_used(_dbuff_or_marker)
Return the number of bytes remaining between the start of the dbuff or marker and the current positio...
Definition dbuff.h:819
#define fr_dbuff_current(_dbuff_or_marker)
Return the 'current' position of a dbuff or marker.
Definition dbuff.h:963
#define fr_dbuff_init(_out, _start, _len_or_end)
Initialise an dbuff for encoding or decoding.
Definition dbuff.h:387
#define fr_dbuff_start(_dbuff_or_marker)
Return the 'start' position of a dbuff or marker.
Definition dbuff.h:950
#define fr_dbuff_remaining(_dbuff_or_marker)
Return the number of bytes remaining between the dbuff or marker and the end of the buffer.
Definition dbuff.h:795
#define fr_dbuff_in_bytes(_dbuff_or_marker,...)
Copy a byte sequence into a dbuff or marker.
Definition dbuff.h:1518
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:177
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
Definition debug.h:248
#define fr_cond_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:194
#define MEM(x)
Definition debug.h:38
#define ERROR(fmt,...)
Definition dhcpclient.c:40
#define DEBUG(fmt,...)
Definition dhcpclient.c:38
int unlang_function_clear(request_t *request)
Clear pending repeat function calls, and remove the signal handler.
Definition function.c:275
int unlang_function_repeat_clear(request_t *request)
Clear the pending repeat function, and keep the signal handler.
Definition function.c:309
#define unlang_function_repeat_set(_request, _repeat)
Set a new repeat function for an existing function frame.
Definition function.h:110
#define unlang_function_push(_request, _func, _repeat, _signal, _sigmask, _top_frame, _uctx)
Push a generic function onto the unlang stack.
Definition function.h:181
talloc_free(hp)
void unlang_interpet_frame_discard(request_t *request)
Discard the bottom most frame on the request's stack.
Definition interpret.c:2511
bool unlang_request_is_cancelled(request_t const *request)
Return whether a request has been cancelled.
Definition interpret.c:1971
#define UNLANG_SUB_FRAME
Definition interpret.h:37
#define REXDENT()
Exdent (unindent) R* messages by one level.
Definition log.h:460
#define ROPTIONAL(_l_request, _l_global, _fmt,...)
Use different logging functions depending on whether request is NULL or not.
Definition log.h:545
#define RWDEBUG(fmt,...)
Definition log.h:378
#define RDEBUG_ENABLED3
True if request debug level 1-3 messages are enabled.
Definition log.h:352
#define RDEBUG3(fmt,...)
Definition log.h:360
#define RHEXDUMP4(_data, _len, _fmt,...)
Definition log.h:723
#define RPEDEBUG(fmt,...)
Definition log.h:393
#define RHEXDUMP3(_data, _len, _fmt,...)
Definition log.h:722
#define RDEBUG4(fmt,...)
Definition log.h:361
#define RDEBUG_ENABLED4
True if request debug level 1-4 messages are enabled.
Definition log.h:353
#define RPWDEBUG2(fmt,...)
Definition log.h:384
#define REDEBUG4(fmt,...)
Definition log.h:391
#define RINDENT()
Indent R* messages by one level.
Definition log.h:447
fr_value_box_t const * enum_tls_packet_type_load_psk
HIDDEN fr_dict_attr_t const * attr_tls_packet_type
HIDDEN fr_dict_attr_t const * attr_session_resumed
HIDDEN fr_dict_attr_t const * attr_tls_session_version
HIDDEN fr_dict_attr_t const * attr_tls_alert_level
fr_value_box_t const * enum_tls_packet_type_success
HIDDEN fr_dict_attr_t const * attr_tls_psk_key
HIDDEN fr_dict_attr_t const * attr_tls_session_require_client_cert
fr_value_box_t const * enum_tls_packet_type_new_session
fr_value_box_t const * enum_tls_packet_type_establish_session
HIDDEN fr_dict_attr_t const * attr_tls_error
fr_value_box_t const * enum_tls_packet_type_fail_session
HIDDEN fr_dict_attr_t const * attr_tls_session_cipher_suite
HIDDEN fr_dict_attr_t const * attr_tls_psk_identity
HIDDEN fr_dict_attr_t const * attr_tls_alert_description
fr_value_box_t const * enum_tls_packet_type_notfound
HIDDEN fr_dict_attr_t const * attr_tls_alert
HIDDEN fr_dict_attr_t const * attr_tls_session_cert_file
@ L_DBG_LVL_3
3rd highest priority debug messages (-xxx | -Xx).
Definition log.h:69
@ L_DBG
Only displayed when debugging is enabled.
Definition log.h:56
static uint8_t fr_low_bit_pos(uint64_t num)
Find the lowest order high bit in an unsigned 64 bit integer.
Definition math.h:113
unsigned int uint32_t
long int ssize_t
unsigned char uint8_t
#define UINT8_MAX
static size_t used
static uint16_t fr_nbo_to_uint16(uint8_t const data[static sizeof(uint16_t)])
Read an unsigned 16bit integer from wire format (big endian)
Definition nbo.h:146
int fr_pair_append_by_da(TALLOC_CTX *ctx, fr_pair_t **out, fr_pair_list_t *list, fr_dict_attr_t const *da)
Alloc a new fr_pair_t (and append)
Definition pair.c:1416
int fr_pair_list_copy(TALLOC_CTX *ctx, fr_pair_list_t *to, fr_pair_list_t const *from)
Duplicate a list of pairs.
Definition pair.c:2303
int fr_pair_value_strdup(fr_pair_t *vp, char const *src, bool tainted)
Copy data into an "string" data type.
Definition pair.c:2598
int fr_pair_value_from_str(fr_pair_t *vp, char const *value, size_t inlen, fr_sbuff_unescape_rules_t const *uerules, UNUSED bool tainted)
Convert string value to native attribute value.
Definition pair.c:2552
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
Definition pair.c:707
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
Definition pair.c:1297
int fr_pair_delete_by_da(fr_pair_list_t *list, fr_dict_attr_t const *da)
Delete matching pairs from the specified list.
Definition pair.c:1641
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
Definition pair.c:47
fr_pair_t * fr_pair_copy(TALLOC_CTX *ctx, fr_pair_t const *vp)
Copy a single valuepair.
Definition pair.c:500
#define fr_assert(_expr)
Definition rad_assert.h:37
#define pair_update_request(_attr, _da)
#define REDEBUG(fmt,...)
#define RDEBUG_ENABLED2()
#define RDEBUG2(fmt,...)
#define DEBUG2(fmt,...)
static rs_t * conf
Definition radsniff.c:52
#define request_is_detachable(_x)
Definition request.h:188
#define pair_append_request(_attr, _da)
Allocate and append a fr_pair_t to the request list.
Definition pair.h:37
#define pair_update_session_state(_attr, _da)
Return or allocate a fr_pair_t in the session_state list.
Definition pair.h:151
#define tmpl_aexpand(_ctx, _out, _request, _vpt, _escape, _escape_ctx)
Expand a tmpl to a C type, allocing a new buffer to hold the string.
Definition tmpl.h:1087
#define FR_SIGNAL_ALLOW(_signals)
Signal mask which blocks every signal except the ones in _signals.
Definition signal.h:58
fr_signal_t
Signals that can be generated/processed by request signal handlers.
Definition signal.h:38
@ FR_SIGNAL_NONE
No signals.
Definition signal.h:39
@ FR_SIGNAL_CANCEL
Request has been cancelled.
Definition signal.h:40
static char buff[sizeof("18446744073709551615")+3]
Definition size_tests.c:37
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Definition snprintf.c:689
fr_pair_t * vp
size_t strlcpy(char *dst, char const *src, size_t siz)
Definition strlcpy.c:34
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
int unlang_subrequest_child_push(unlang_result_t *p_result, request_t *child, void const *unique_session_ptr, bool free_child, bool top_frame)
Push a pre-existing child back onto the stack as a subrequest.
Definition subrequest.c:440
static size_t talloc_strlen(char const *s)
Returns the length of a talloc array containing a string.
Definition talloc.h:143
static fr_slen_t parent
Definition pair.h:864
static fr_slen_t data
Definition value.h:1366
#define fr_value_box_init_null(_vb)
Initialise an empty/null box that will be filled later.
Definition value.h:640
static fr_sbuff_err_t char size_t * len
Definition value.h:1061