26RCSID(
"$Id: 1f2105e4dbbb699744a38c2c79b12ec1e2110eaa $")
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>
50#define TLS_TICKET_STATEFUL_DISABLED (!tls_cache || !conf->virtual_server)
52static inline CC_HINT(always_inline,
nonnull(2))
53void _tls_ticket_stateful_load_state_reset(
request_t *
request, fr_tls_ticket_stateful_t *cache,
char const *func)
55 if (cache->load.sess) {
57 ROPTIONAL(
RDEBUG3,
DEBUG3,
"(TLS) Session ID %pV - Freeing loaded session in %s", cache->session_id, func);
60 SSL_SESSION_free(cache->load.sess);
61 cache->load.sess = NULL;
63 cache->load.state = FR_TLS_TICKET_STATEFUL_INIT;
65#define tls_ticket_stateful_load_state_reset(_request, _cache) _tls_ticket_stateful_load_state_reset(_request, _cache, __FUNCTION__)
67static inline CC_HINT(always_inline,
nonnull(2))
68void _tls_ticket_stateful_store_state_reset(
request_t *
request, fr_tls_ticket_stateful_t *cache,
char const *func)
70 if (cache->store.sess) {
72 ROPTIONAL(
RDEBUG3,
DEBUG3,
"(TLS) Session ID %pV - Freeing session to store in %s", &cache->store.id, func);
74 SSL_SESSION_free(cache->store.sess);
75 cache->store.sess = NULL;
78 cache->store.state = FR_TLS_TICKET_STATEFUL_INIT;
80#define tls_ticket_stateful_store_state_reset(_request, _cache) _tls_ticket_stateful_store_state_reset(_request, _cache, __FUNCTION__)
82static inline CC_HINT(always_inline)
83void _tls_ticket_stateful_clear_state_reset(
request_t *
request, fr_tls_ticket_stateful_t *cache,
char const *func)
88 &cache->clear.id, func);
92 cache->clear.state = FR_TLS_TICKET_STATEFUL_INIT;
94#define tls_ticket_stateful_clear_state_reset(_request, _cache) _tls_ticket_stateful_clear_state_reset(_request, _cache, __FUNCTION__)
98static inline CC_HINT(always_inline)
void tls_ticket_stateful_load_state_request(fr_tls_session_t *tls_session)
100 tls_session->cache->load.state = FR_TLS_TICKET_STATEFUL_REQUESTED;
101 TLS_PENDING_SET(tls_session, FR_TLS_PENDING_STATEFUL_TICKET);
106static inline CC_HINT(always_inline)
void tls_ticket_stateful_store_state_request(fr_tls_session_t *tls_session)
108 tls_session->cache->store.state = FR_TLS_TICKET_STATEFUL_REQUESTED;
109 TLS_PENDING_SET(tls_session, FR_TLS_PENDING_STATEFUL_TICKET);
114static inline CC_HINT(always_inline)
void tls_ticket_stateful_clear_state_request(fr_tls_session_t *tls_session)
116 tls_session->cache->clear.state = FR_TLS_TICKET_STATEFUL_REQUESTED;
117 TLS_PENDING_SET(tls_session, FR_TLS_PENDING_STATEFUL_TICKET);
124static void tls_ticket_stateful_delete_request(fr_tls_session_t *tls_session, SSL_SESSION *sess)
126 fr_tls_ticket_stateful_t *tls_cache;
129 if (!tls_session->cache)
return;
131 request = fr_tls_session_request(tls_session->ssl);
132 tls_cache = tls_session->cache;
139 fr_assert(tls_cache->clear.state == FR_TLS_TICKET_STATEFUL_INIT);
144 if (tls_ticket_id_to_box(tls_cache, &tls_cache->clear.id, sess) < 0) {
145 RWDEBUG(
"(TLS) Error retrieving Session ID");
149 RDEBUG3(
"(TLS) Session ID %pV - Requested session clear", &tls_cache->clear.id);
151 tls_ticket_stateful_clear_state_request(tls_session);
157 tls_ticket_stateful_store_state_reset(
request, tls_cache);
167 if (tls_session->session) {
169 tls_session->session = NULL;
185 if (tls_session->can_pause) ASYNC_pause_job();
192 fr_tls_session_t *tls_session = talloc_get_type_abort(uctx, fr_tls_session_t);
193 fr_tls_ticket_stateful_t *tls_cache = tls_session->cache;
200 RWDEBUG(
"(TLS) Failed acquiring session data");
208 fr_tls_session_error_add(
request->parent,
210 FR_ERROR_VALUE_LOAD_SESSION_NOT_FOUND :
211 FR_ERROR_VALUE_LOAD_SESSION_FAILED);
213 tls_cache->load.state = FR_TLS_TICKET_STATEFUL_FAILED;
219 RWDEBUG(
"(TLS) No cached session found");
220 fr_tls_session_error_add(
request->parent, FR_ERROR_VALUE_LOAD_SESSION_NOT_FOUND);
225 p = (
unsigned char const **)&q;
227 sess = d2i_SSL_SESSION(NULL, p,
vp->vp_length);
229 fr_tls_log_perror(
request,
"Failed loading persisted session");
230 fr_tls_session_error_add(
request->parent, FR_ERROR_VALUE_LOAD_SESSION_MALFORMED);
234 tls_session_id_cache(tls_session, sess);
237 RDEBUG3(
"(TLS) Session ID %pV - Read %zu bytes of data. "
238 "Session de-serialized successfully", &tls_session->session_id,
vp->vp_length);
253 fr_tls_conf_t *
conf = tls_session->conf;
255 if (!tls_ticket_session_resumable(
request, &tls_session->session_id,
conf, sess)) {
256 RWDEBUG(
"(TLS) Session ID %pV - Cached session has too little life left, not resuming",
257 &tls_session->session_id);
258 fr_tls_session_error_add(
request, FR_ERROR_VALUE_LOAD_SESSION_EXPIRED);
265 SSL_SESSION_free(sess);
279 SSL_SESSION_set_ex_data(sess, fr_tls_session_ex_index, fr_tls_session(tls_session->ssl));
281 tls_cache->load.state = FR_TLS_TICKET_STATEFUL_SUCCESS;
282 tls_cache->load.sess = sess;
289 tls_cache->loaded =
true;
305 fr_tls_ticket_stateful_t *tls_cache = tls_session->cache;
306 fr_tls_conf_t *
conf = tls_session->conf;
324 if (tls_cache->clear.state == FR_TLS_TICKET_STATEFUL_REQUESTED) {
325 RDEBUG3(
"(TLS) Session ID %pV - Clear is pending, skipping `load session { ... }`",
326 &tls_cache->load.id);
327 tls_cache->load.state = FR_TLS_TICKET_STATEFUL_FAILED;
334 &tls_cache->load.id));
340 ua = fr_tls_call_push(child, tls_ticket_stateful_load_resume,
conf, tls_session,
true);
343 tls_ticket_stateful_load_state_reset(
request, tls_cache);
354 fr_tls_session_t *tls_session = talloc_get_type_abort(uctx, fr_tls_session_t);
355 fr_tls_ticket_stateful_t *tls_cache = tls_session->cache;
358 tls_ticket_stateful_store_state_reset(
request, tls_cache);
362 tls_cache->store.state = FR_TLS_TICKET_STATEFUL_SUCCESS;
364 RWDEBUG(
"(TLS) Failed storing session data");
365 fr_tls_session_error_add(
request->parent, FR_ERROR_VALUE_STORE_SESSION_FAILED);
366 tls_cache->store.state = FR_TLS_TICKET_STATEFUL_INIT;
382static inline CC_HINT(always_inline)
385 fr_tls_ticket_stateful_t *tls_cache = tls_session->cache;
393 SSL_SESSION *sess = tls_session->cache->store.sess;
400 fr_assert(tls_cache->store.state == FR_TLS_TICKET_STATEFUL_REQUESTED);
408 if (tls_cache->clear.state == FR_TLS_TICKET_STATEFUL_REQUESTED) {
409 RWDEBUG(
"(TLS) Session ID %pV - Clear is pending, not storing", &tls_cache->store.id);
410 fr_tls_session_error_add(
request, FR_ERROR_VALUE_STORE_CANCELLED_BY_CLEAR);
411 tls_ticket_stateful_store_state_reset(
request, tls_cache);
415 ttl = tls_ticket_session_lifetime(
request, &tls_cache->store.id,
conf, sess);
417 RWDEBUG(
"(TLS) Session ID %pV - Session has already expired, not storing", &tls_cache->store.id);
418 fr_tls_session_error_add(
request, FR_ERROR_VALUE_STORE_SESSION_EXPIRED);
426 rcode = tls_ticket_app_data_set(
request, sess, &tls_cache->store.id);
428 tls_ticket_stateful_store_state_reset(
request, tls_cache);
435 &tls_cache->store.id));
443 vp->vp_time_delta = ttl;
448 ret = i2d_SSL_SESSION(sess, NULL);
451 fr_tls_strerror_printf(NULL);
452 RPWDEBUG(
"(TLS) Session ID %pV - Serialisation failed, couldn't determine "
453 "required buffer length", &tls_cache->store.id);
455 tls_ticket_stateful_store_state_reset(
request, tls_cache);
466 ret = i2d_SSL_SESSION(sess, &p);
468 fr_tls_strerror_printf(NULL);
469 RPWDEBUG(
"(TLS) Session ID %pV - Serialisation failed", &tls_cache->store.id);
479 ua = fr_tls_call_push(child, tls_ticket_stateful_store_resume,
conf, tls_session,
true);
489 fr_tls_session_t *tls_session = talloc_get_type_abort(uctx, fr_tls_session_t);
490 fr_tls_ticket_stateful_t *tls_cache = tls_session->cache;
493 tls_ticket_stateful_clear_state_reset(
request, tls_cache);
502 RWDEBUG(
"(TLS) Failed deleting session data - security may be compromised");
503 fr_tls_session_error_add(
request->parent, FR_ERROR_VALUE_CLEAR_SESSION_FAILED);
517static inline CC_HINT(always_inline)
521 fr_tls_ticket_stateful_t *tls_cache = tls_session->cache;
526 fr_assert(tls_cache->clear.state == FR_TLS_TICKET_STATEFUL_REQUESTED);
530 &tls_cache->clear.id));
536 ua = fr_tls_call_push(child, tls_ticket_stateful_clear_resume,
conf, tls_session,
true);
539 tls_ticket_stateful_clear_state_reset(
request, tls_cache);
554 fr_tls_session_t *tls_session = talloc_get_type_abort(uctx, fr_tls_session_t);
555 fr_tls_ticket_stateful_t *tls_cache = tls_session->cache;
557 (void) tls_ticket_stateful_load_resume(
request, uctx);
559 if (tls_cache->load.state != FR_TLS_TICKET_STATEFUL_SUCCESS) {
560 RDEBUG2(
"(TLS) No session to resume");
564 if (SSL_set_session(tls_session->ssl, tls_cache->load.sess) != 1) {
565 fr_tls_log_perror(
request,
"Failed setting the session to resume");
566 tls_ticket_stateful_load_state_reset(
request, tls_cache);
570 RDEBUG2(
"(TLS) Offering the cached session for resumption");
577 tls_ticket_stateful_load_state_reset(
request, tls_cache);
603 fr_tls_ticket_stateful_t *tls_cache = tls_session->cache;
604 fr_tls_conf_t *
conf = tls_session->conf;
615 RPEDEBUG(
"(TLS) Failed expanding the session name");
624 ua = fr_tls_call_push(child, tls_ticket_stateful_load_client_resume,
conf, tls_session,
true);
645 fr_tls_ticket_stateful_t *tls_cache = tls_session->cache;
646 fr_tls_conf_t *
conf = tls_session->conf;
656 if (TLS_TICKET_STATEFUL_DISABLED) {
657 if (tls_cache->load.state == FR_TLS_TICKET_STATEFUL_REQUESTED) {
658 tls_ticket_stateful_load_state_reset(
request, tls_cache);
660 if (tls_cache->clear.state == FR_TLS_TICKET_STATEFUL_REQUESTED) {
661 tls_ticket_stateful_clear_state_reset(
request, tls_cache);
663 if (tls_cache->store.state == FR_TLS_TICKET_STATEFUL_REQUESTED) {
664 tls_ticket_stateful_store_state_reset(
request, tls_cache);
677 if (tls_cache->load.state == FR_TLS_TICKET_STATEFUL_REQUESTED) {
678 ua = tls_ticket_stateful_load_push(
request, tls_session);
686 if (tls_cache->clear.state == FR_TLS_TICKET_STATEFUL_REQUESTED) {
691 fr_assert(tls_cache->store.state != FR_TLS_TICKET_STATEFUL_REQUESTED);
692 tls_ticket_stateful_store_state_reset(
request, tls_cache);
694 return tls_ticket_stateful_clear_push(
request,
conf, tls_session);
697 if (tls_cache->store.state == FR_TLS_TICKET_STATEFUL_REQUESTED) {
698 return tls_ticket_stateful_store_push(
request,
conf, tls_session);
718 fr_tls_session_t *tls_session = talloc_get_type_abort(uctx, fr_tls_session_t);
728 ua = fr_tls_ticket_stateful_pending_push(
request, tls_session);
740 REDEBUG(
"(TLS) Failed running session cache operations");
784 return tls_ticket_stateful_drain_push(
request, tls_session);
805 fr_tls_ticket_stateful_t *tls_cache = tls_session->cache;
814 bound = fr_tls_session_request_bound(tls_session->ssl);
822 fr_tls_session_request_bind(tls_session->ssl,
request);
845 if (tls_session->session) {
846 SSL_CTX_remove_session(tls_session->ctx, tls_session->session);
854 if (tls_session->session && tls_cache->loaded) tls_ticket_stateful_delete_request(tls_session, tls_session->session);
856 tls_session->allow_session_resumption =
false;
861 tls_ticket_stateful_store_state_reset(
request, tls_cache);
866 if (!bound) fr_tls_session_request_unbind(tls_session->ssl);
868 return tls_ticket_stateful_drain_push(
request, tls_session);
884static int tls_ticket_stateful_store_cb(SSL *ssl, SSL_SESSION *sess)
887 fr_tls_session_t *tls_session;
888 fr_tls_ticket_stateful_t *tls_cache;
895 tls_session = fr_tls_session(ssl);
896 request = fr_tls_session_request(tls_session->ssl);
912 if (tls_session->session_ticket_created) {
913 RDEBUG2(
"(TLS) Stateless ticket already created, not performing stateful store");
940 if (tls_session->seen_application_data) {
941 RDEBUG2(
"(TLS) Ignoring session ticket received after application data started");
948 tls_session->session_ticket_received =
true;
960 fr_assert(!tls_session->session || !SSL_is_server(ssl));
961 tls_session->session = sess;
962 tls_session_id_cache(tls_session, sess);
964 tls_cache = tls_session->cache;
967 fr_assert(tls_session->conf->virtual_server);
984 if (tls_ticket_id_to_box(tls_cache, &tls_cache->store.id, sess) < 0) {
985 RDEBUG3(
"(TLS) No Session ID to store");
989 RDEBUG3(
"(TLS) Session ID %pV - Requested store", &tls_cache->store.id);
995 tls_cache->store.sess = sess;
996 tls_ticket_stateful_store_state_request(tls_session);
1013static SSL_SESSION *tls_ticket_stateful_load_cb(SSL *ssl,
1014 unsigned char const *key,
1015 int key_len,
int *copy)
1017 fr_tls_session_t *tls_session;
1018 fr_tls_ticket_stateful_t *tls_cache;
1021 tls_session = fr_tls_session(ssl);
1022 request = fr_tls_session_request(tls_session->ssl);
1023 tls_cache = tls_session->cache;
1026 fr_assert(tls_session->conf->virtual_server);
1038 if (!tls_cache || !tls_session->allow_session_resumption)
return NULL;
1066 switch (tls_cache->load.state) {
1067 case FR_TLS_TICKET_STATEFUL_INIT:
1070 tls_ticket_stateful_load_state_request(tls_session);
1072 (
uint8_t const *)key, key_len,
true) == 0);
1083 (
uint8_t const *)key, key_len,
true) == 0);
1084 if (tls_cache) tls_cache->session_id = &tls_session->session_id;
1087 RDEBUG3(
"(TLS) Requested session load - ID %pV", &tls_cache->load.id);
1097 if (
unlikely(!tls_session->can_pause)) {
1100 "tls_session_async_handshake_cont must be in call stack", __FUNCTION__);
1119 tls_ticket_stateful_load_state_reset(
request, tls_cache);
1125 case FR_TLS_TICKET_STATEFUL_REQUESTED:
1127 tls_cache->load.state = FR_TLS_TICKET_STATEFUL_FAILED;
1130 case FR_TLS_TICKET_STATEFUL_SUCCESS:
1140 tls_session_id_cache(tls_session, tls_cache->load.sess);
1142 RDEBUG3(
"(TLS) Setting session data");
1155 if (tls_ticket_app_data_get(
request, tls_cache->load.sess, &tls_session->session_id) < 0) {
1156 REDEBUG(
"(TLS) Denying session resumption via session-id");
1163 tls_ticket_stateful_delete_request(tls_session, tls_cache->load.sess);
1164 tls_ticket_stateful_load_state_reset(
request, tls_session->cache);
1173 fr_tls_verify_resumed_request(tls_session);
1175 if (
unlikely(!tls_session->can_pause))
goto cant_pause;
1192 tls_ticket_stateful_load_state_reset(
request, tls_cache);
1193 fr_tls_verify_cert_reset(tls_session);
1202 if (!fr_tls_verify_cert_result(tls_session)) {
1203 RDEBUG2(
"(TLS) Certificate re-validation failed, denying session resumption via session-id");
1206 sess = tls_cache->load.sess;
1215 RDEBUG3(
"(TLS) Session ID %pV - Session ownership transferred to libssl", &tls_session->session_id);
1217 tls_cache->load.sess = NULL;
1223 case FR_TLS_TICKET_STATEFUL_FAILED:
1224 RDEBUG3(
"(TLS) Session data load failed");
1239static void tls_ticket_stateful_delete_cb(
UNUSED SSL_CTX *ctx, SSL_SESSION *sess)
1241 fr_tls_session_t *tls_session;
1249 tls_session = SSL_SESSION_get_ex_data(sess, fr_tls_session_ex_index);
1250 if (!tls_session)
return;
1252 (void) talloc_get_type_abort(tls_session, fr_tls_session_t);
1259 tls_ticket_stateful_delete_request(tls_session, sess);
1264static int _tls_ticket_stateful_free(fr_tls_ticket_stateful_t *tls_cache)
1266 tls_ticket_stateful_load_state_reset(NULL, tls_cache);
1267 tls_ticket_stateful_store_state_reset(NULL, tls_cache);
1278void fr_tls_ticket_stateful_session_alloc(fr_tls_session_t *tls_session)
1282 MEM(tls_session->cache = talloc_zero(tls_session, fr_tls_ticket_stateful_t));
1283 talloc_set_destructor(tls_session->cache, _tls_ticket_stateful_free);
1290void fr_tls_ticket_stateful_disable(SSL_CTX *ctx)
1303 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
1318void fr_tls_ticket_stateful_ctx_init(SSL_CTX *ctx, fr_tls_ticket_conf_t
const *cache_conf,
bool client)
1320 SSL_CTX_sess_set_new_cb(ctx, tls_ticket_stateful_store_cb);
1321 SSL_CTX_sess_set_get_cb(ctx, tls_ticket_stateful_load_cb);
1322 SSL_CTX_sess_set_remove_cb(ctx, tls_ticket_stateful_delete_cb);
1324 SSL_CTX_set_session_cache_mode(ctx, (client ? SSL_SESS_CACHE_CLIENT : SSL_SESS_CACHE_SERVER) |
1325 SSL_SESS_CACHE_NO_INTERNAL);
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
@ UNLANG_ACTION_PUSHED_CHILD
unlang_t pushed a new child onto the stack, execute it instead of continuing.
@ 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 USES_APPLE_DEPRECATED_API
#define IGNORE(_expr, _type)
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
int unlang_function_clear(request_t *request)
Clear pending repeat function calls, and remove the signal handler.
#define unlang_function_repeat_set(_request, _repeat)
Set a new repeat function for an existing function frame.
#define unlang_function_push(_request, _func, _repeat, _signal, _sigmask, _top_frame, _uctx)
Push a generic function onto the unlang stack.
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 RDEBUG_ENABLED3
True if request debug level 1-3 messages are enabled.
#define ROPTIONAL_ENABLED(_e_request, _e_global)
Check if a debug level is set by the request (if !NULL) or by the global log.
#define RPEDEBUG(fmt,...)
#define RPWDEBUG(fmt,...)
#define DEBUG_ENABLED3
True if global debug level 1-3 messages are enabled.
fr_value_box_t const * enum_tls_packet_type_store_session
HIDDEN fr_dict_attr_t const * attr_tls_packet_type
fr_value_box_t const * enum_tls_packet_type_success
HIDDEN fr_dict_attr_t const * attr_tls_session_ttl
HIDDEN fr_dict_attr_t const * attr_tls_session_data
fr_value_box_t const * enum_tls_packet_type_load_session
fr_value_box_t const * enum_tls_packet_type_clear_session
fr_value_box_t const * enum_tls_packet_type_notfound
@ L_DBG_LVL_3
3rd highest priority debug messages (-xxx | -Xx).
@ L_DBG
Only displayed when debugging is enabled.
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.
int fr_pair_value_memdup_buffer_shallow(fr_pair_t *vp, uint8_t const *src, bool tainted)
Assign a talloced buffer to a "octets" type value pair.
#define pair_update_request(_attr, _da)
#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.
@ FR_SIGNAL_NONE
No signals.
Stores an attribute, a value and various bits of other data.
static size_t talloc_strlen(char const *s)
Returns the length of a talloc array containing a string.
#define fr_time_delta_ispos(_a)
static int64_t fr_time_delta_to_sec(fr_time_delta_t delta)
A time delta, a difference in time measured in nanoseconds.
#define fr_type_is_null(_x)
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
int fr_value_box_memdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, uint8_t const *src, size_t len, bool tainted)
Copy a buffer to a fr_value_box_t.
static fr_sbuff_err_t char size_t * len
#define fr_box_octets(_val, _len)