26RCSID(
"$Id: 377e6b880f38e5236fda421b1065302ba4b18557 $")
30#define LOG_PREFIX "tls"
33#include <freeradius-devel/internal/internal.h>
34#include <freeradius-devel/server/pair.h>
35#include <freeradius-devel/unlang/function.h>
36#include <freeradius-devel/unlang/subrequest.h>
37#include <freeradius-devel/util/debug.h>
39#include <freeradius-devel/protocol/tls/freeradius.h>
48#include <openssl/ssl.h>
49#include <openssl/kdf.h>
57 fr_tls_session_t *tls_session = talloc_get_type_abort(uctx, fr_tls_session_t);
60 fr_assert((tls_session->ticket == FR_TLS_TICKET_STATELESS_ENCODE_REQUESTED) ||
61 (tls_session->ticket == FR_TLS_TICKET_STATELESS_DECODE_REQUESTED));
65 tls_session->ticket = FR_TLS_TICKET_STATELESS_FAILED;
69 tls_session->ticket = FR_TLS_TICKET_STATELESS_SUCCESS;
86 fr_tls_conf_t *
conf = tls_session->conf;
92 MEM(child = tls_subrequest_alloc(
request, packet_type, &tls_session->session_id));
94 fr_tls_session_extra_pairs_copy_to_child(child, tls_session);
96 ua = fr_tls_call_push(child, tls_ticket_stateless_resume,
conf, tls_session,
false);
98 REDEBUG(
"(TLS) Failed calling TLS virtual server");
117 switch (tls_session->ticket) {
118 case FR_TLS_TICKET_STATELESS_ENCODE_REQUESTED:
119 return tls_ticket_stateless_push(
request, tls_session,
122 case FR_TLS_TICKET_STATELESS_DECODE_REQUESTED:
123 return tls_ticket_stateless_push(
request, tls_session,
133static inline CC_HINT(always_inline)
void tls_ticket_stateless_encode_request(fr_tls_session_t *tls_session)
135 tls_session->ticket = FR_TLS_TICKET_STATELESS_ENCODE_REQUESTED;
136 TLS_PENDING_SET(tls_session, FR_TLS_PENDING_STATELESS_TICKET);
141static inline CC_HINT(always_inline)
void tls_ticket_stateless_decode_request(fr_tls_session_t *tls_session)
143 tls_session->ticket = FR_TLS_TICKET_STATELESS_DECODE_REQUESTED;
144 TLS_PENDING_SET(tls_session, FR_TLS_PENDING_STATELESS_TICKET);
163static inline CC_HINT(always_inline)
164bool tls_ticket_stateless_section_run(
request_t *
request, fr_tls_session_t *tls_session,
172 if (
unlikely(!tls_session->can_pause)) {
174 "tls_session_async_handshake_cont must be in call stack", __FUNCTION__);
175 tls_session->ticket = FR_TLS_TICKET_STATELESS_INIT;
186 tls_session->ticket = FR_TLS_TICKET_STATELESS_INIT;
190 if (tls_session->ticket != FR_TLS_TICKET_STATELESS_SUCCESS) {
191 REDEBUG(
"(TLS) `%s` did not return success",
name);
192 fr_tls_session_error_add(
request, error);
193 tls_session->ticket = FR_TLS_TICKET_STATELESS_INIT;
197 tls_session->ticket = FR_TLS_TICKET_STATELESS_INIT;
210static bool tls_ticket_stateless_encode_run(
request_t *
request, fr_tls_session_t *tls_session)
212 fr_assert(tls_session->ticket == FR_TLS_TICKET_STATELESS_INIT);
214 tls_ticket_stateless_encode_request(tls_session);
216 return tls_ticket_stateless_section_run(
request, tls_session,
"encode session",
217 FR_ERROR_VALUE_ENCODE_SESSION_FAILED);
228static bool tls_ticket_stateless_decode_run(
request_t *
request, fr_tls_session_t *tls_session)
230 fr_assert(tls_session->ticket == FR_TLS_TICKET_STATELESS_INIT);
232 tls_ticket_stateless_decode_request(tls_session);
234 return tls_ticket_stateless_section_run(
request, tls_session,
"decode session",
235 FR_ERROR_VALUE_DECODE_SESSION_FAILED);
243void fr_tls_ticket_stateless_disable(SSL_CTX *ctx,
bool stateful)
245 long ctx_options = SSL_CTX_get_options(ctx);
250 ctx_options |= SSL_OP_NO_TICKET;
251 SSL_CTX_set_options(ctx, ctx_options);
258 SSL_CTX_set_num_tickets(ctx, stateful ? 1 : 0);
267static int tls_ticket_stateless_app_data_set(SSL *ssl,
void *arg)
269 fr_tls_session_t *tls_session = fr_tls_session(ssl);
270 fr_tls_ticket_conf_t *tls_cache_conf = arg;
282 if (!fr_tls_session_request_bound(ssl))
return 1;
288 if (!tls_session->session_ticket_supported)
return 1;
296 request = fr_tls_session_request(ssl);
308 if (!tls_session->allow_session_resumption ||
309 (!(tls_cache_conf->mode & FR_TLS_TICKET_STATELESS))) {
310 REDEBUG(
"(TLS) Generating session-tickets is not allowed");
311 fr_tls_session_error_add(
request, FR_ERROR_VALUE_SESSION_TICKET_NOT_ALLOWED);
315 sess = SSL_get_session(ssl);
317 REDEBUG(
"(TLS) Failed retrieving session in session generation callback");
326 conf = fr_tls_session_conf(ssl);
328 if (
conf->encode_session && !tls_ticket_stateless_encode_run(
request, tls_session)) {
329 REDEBUG(
"(TLS) Not generating a session-ticket");
333 ret = tls_ticket_app_data_set(
request, sess, &tls_session->session_id);
334 if (ret == 1) tls_session->session_ticket_created =
true;
343static SSL_TICKET_RETURN tls_ticket_stateless_app_data_get(SSL *ssl, SSL_SESSION *sess,
344 UNUSED unsigned char const *keyname,
345 UNUSED size_t keyname_len,
346 SSL_TICKET_STATUS status,
349 fr_tls_session_t *tls_session = fr_tls_session(ssl);
350 fr_tls_conf_t *
conf = tls_session->conf;
351 fr_tls_ticket_conf_t *tls_cache_conf = arg;
354 if (fr_tls_session_request_bound(ssl)) {
355 request = fr_tls_session_request(ssl);
359 if (!tls_session->allow_session_resumption ||
360 (!(tls_cache_conf->mode & FR_TLS_TICKET_STATELESS))) {
362 "denying session resumption via session-ticket");
363 return SSL_TICKET_RETURN_IGNORE;
367 case SSL_TICKET_EMPTY:
368 case SSL_TICKET_NO_DECRYPT:
369 case SSL_TICKET_FATAL_ERR_MALLOC:
370 case SSL_TICKET_FATAL_ERR_OTHER:
371 case SSL_TICKET_NONE:
372#ifdef STATIC_ANALYZER
375 return SSL_TICKET_RETURN_IGNORE_RENEW;
377 case SSL_TICKET_SUCCESS:
378 if (!
request)
return SSL_TICKET_RETURN_USE;
381 case SSL_TICKET_SUCCESS_RENEW:
382 if (!
request)
return SSL_TICKET_RETURN_USE_RENEW;
401 if (!tls_ticket_session_resumable(
request, &tls_session->session_id,
conf, sess)) {
402 REDEBUG(
"(TLS) Session-ticket has too little life left, denying session resumption");
403 fr_tls_session_error_add(
request, FR_ERROR_VALUE_SESSION_TICKET_EXPIRED);
404 return SSL_TICKET_RETURN_IGNORE_RENEW;
407 if (tls_ticket_app_data_get(
request, sess, &tls_session->session_id) < 0) {
408 REDEBUG(
"(TLS) Denying session resumption via session-ticket");
409 return SSL_TICKET_RETURN_IGNORE_RENEW;
417 if (
conf->decode_session && !tls_ticket_stateless_decode_run(
request, tls_session)) {
418 REDEBUG(
"(TLS) Denying session resumption via session-ticket");
419 return SSL_TICKET_RETURN_IGNORE_RENEW;
422 if (
conf->virtual_server && tls_session->verify_peer_cert) {
423 RDEBUG2(
"(TLS) Requesting certificate re-validation for session-ticket");
432 fr_tls_verify_resumed_request(tls_session);
440 if (
unlikely(!tls_session->can_pause)) {
442 "tls_session_async_handshake_cont must be in call stack", __FUNCTION__);
443 return SSL_TICKET_RETURN_IGNORE_RENEW;
460 fr_tls_verify_cert_reset(tls_session);
461 return SSL_TICKET_RETURN_ABORT;
469 if (!fr_tls_verify_cert_result(tls_session)) {
470 RDEBUG2(
"(TLS) Certificate re-validation failed, denying session resumption via session-ticket");
471 return SSL_TICKET_RETURN_IGNORE_RENEW;
475 return (status == SSL_TICKET_SUCCESS_RENEW) ? SSL_TICKET_RETURN_USE_RENEW : SSL_TICKET_RETURN_USE;
491int fr_tls_ticket_stateless_ctx_init(SSL_CTX *ctx, fr_tls_ticket_conf_t
const *cache_conf)
495 EVP_PKEY_CTX *pkey_ctx = NULL;
506 key_len = SSL_CTX_set_tlsext_ticket_keys(ctx, NULL, 0);
508 if (
unlikely((pkey_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL)) == NULL)) {
509 fr_tls_strerror_printf(NULL);
510 PERROR(
"Failed initialising KDF");
512 if (pkey_ctx) EVP_PKEY_CTX_free(pkey_ctx);
515 if (
unlikely(EVP_PKEY_derive_init(pkey_ctx) != 1)) {
516 fr_tls_strerror_printf(NULL);
517 PERROR(
"Failed initialising KDF derivation ctx");
520 if (
unlikely(EVP_PKEY_CTX_set_hkdf_md(pkey_ctx,
UNCONST(
struct evp_md_st *, EVP_sha256())) != 1)) {
521 fr_tls_strerror_printf(NULL);
522 PERROR(
"Failed setting KDF MD");
525 if (
unlikely(EVP_PKEY_CTX_set1_hkdf_key(pkey_ctx,
526 UNCONST(
unsigned char *, cache_conf->session_ticket_key),
527 talloc_array_length(cache_conf->session_ticket_key)) != 1)) {
528 fr_tls_strerror_printf(NULL);
529 PERROR(
"Failed setting KDF key");
532 if (
unlikely(EVP_PKEY_CTX_add1_hkdf_info(pkey_ctx,
533 UNCONST(
unsigned char *,
"freeradius-session-ticket"),
534 sizeof(
"freeradius-session-ticket") - 1) != 1)) {
535 fr_tls_strerror_printf(NULL);
536 PERROR(
"Failed setting KDF label");
544 MEM(key_buff = talloc_array(NULL,
uint8_t, key_len));
545 if (EVP_PKEY_derive(pkey_ctx, key_buff, &key_len) != 1) {
546 fr_tls_strerror_printf(NULL);
547 PERROR(
"Failed deriving session ticket key");
553 EVP_PKEY_CTX_free(pkey_ctx);
556 fr_assert(talloc_array_length(key_buff) == key_len);
561 if (SSL_CTX_set_tlsext_ticket_keys(ctx,
562 key_buff, key_len) != 1) {
563 fr_tls_strerror_printf(NULL);
564 PERROR(
"Failed setting session ticket keys");
568 DEBUG3(
"Derived session-ticket-key:");
570 TALLOC_FREE(key_buff);
576 if (
unlikely(SSL_CTX_set_session_ticket_cb(ctx,
577 tls_ticket_stateless_app_data_set,
578 tls_ticket_stateless_app_data_get,
579 UNCONST(fr_tls_ticket_conf_t *, cache_conf)) != 1)) {
580 fr_tls_strerror_printf(NULL);
581 PERROR(
"Failed setting session ticket callbacks");
591 SSL_CTX_set_num_tickets(ctx, 1);
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
@ UNLANG_ACTION_FAIL
Encountered an unexpected error.
@ UNLANG_ACTION_CALCULATE_RESULT
Calculate a new section rlm_rcode_t value.
static uint8_t request[4]
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
#define USES_APPLE_DEPRECATED_API
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
bool unlang_request_is_cancelled(request_t const *request)
Return whether a request has been cancelled.
#define ROPTIONAL(_l_request, _l_global, _fmt,...)
Use different logging functions depending on whether request is NULL or not.
#define HEXDUMP3(_data, _len, _fmt,...)
HIDDEN fr_dict_attr_t const * attr_tls_packet_type
fr_value_box_t const * enum_tls_packet_type_success
fr_value_box_t const * enum_tls_packet_type_decode_session
fr_value_box_t const * enum_tls_packet_type_encode_session
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.
Stores an attribute, a value and various bits of other data.