The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
cache.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: 896d93d9d792dbbd32e888dacfa5c94d5a52b13c $
19  *
20  * @file tls/cache.c
21  * @brief Functions to support TLS session resumption
22  *
23  * @copyright 2015-2016 The FreeRADIUS server project
24  * @copyright 2021 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
25  */
26 RCSID("$Id: 896d93d9d792dbbd32e888dacfa5c94d5a52b13c $")
27 USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */
28 
29 #ifdef WITH_TLS
30 #define LOG_PREFIX "tls"
31 
32 #include <freeradius-devel/internal/internal.h>
33 #include <freeradius-devel/server/pair.h>
34 #include <freeradius-devel/server/module_rlm.h>
35 #include <freeradius-devel/unlang/function.h>
36 #include <freeradius-devel/unlang/subrequest.h>
37 #include <freeradius-devel/unlang/interpret.h>
38 #include <freeradius-devel/util/debug.h>
39 
40 #include "attrs.h"
41 #include "base.h"
42 #include "cache.h"
43 #include "log.h"
44 #include "strerror.h"
45 #include "verify.h"
46 
47 #include <openssl/ssl.h>
48 #include <openssl/kdf.h>
49 
50 /** Retrieve session ID (in binary form) from the session
51  *
52  * @param[in] ctx Where to allocate the array to hold the session id.
53  * @param[in] sess to retrieve the ID for.
54  * @return A copy of the session id.
55  */
56 uint8_t *fr_tls_cache_id(TALLOC_CTX *ctx, SSL_SESSION *sess)
57 {
58  unsigned int len;
59  uint8_t const *id;
60 
61  id = SSL_SESSION_get_id(sess, &len);
62  if (unlikely(!id)) return NULL;
63 
64  return talloc_typed_memdup(ctx, id, len);
65 }
66 
67 /** Retrieve session ID (in binary form), and assign it to a box
68  *
69  * @note Box will be reinitialised
70  *
71  * @param[out] out Where to write the session ID.
72  * @param[in] sess to retrieve the ID for.
73  */
74 static inline CC_HINT(always_inline, nonnull)
75 int fr_tls_cache_id_to_box_shallow(fr_value_box_t *out, SSL_SESSION *sess)
76 {
77  unsigned int len;
78  uint8_t const *id;
79 
80  id = SSL_SESSION_get_id(sess, &len);
81  if (unlikely(!id)) return -1;
82 
83  fr_value_box_memdup_shallow(out, NULL, id, len, true);
84 
85  return 0;
86 }
87 
88 /** Create a temporary boxed version of the session ID
89  *
90  * @param[out] _box to place on the stack.
91  * @param[in] _sess to write to box.
92  */
93 #define SESSION_ID(_box, _sess) \
94 fr_value_box_t _box; \
95 if (unlikely(fr_tls_cache_id_to_box_shallow(&_box, _sess) < 0)) fr_value_box_init_null(&_box)
96 
97 
98 /** Add an attribute specifying the session id for the operation to be performed with.
99  *
100  * Adds the following attributes to the request:
101  *
102  * - &request.Session-Id
103  *
104  * Session identity will contain the binary session key used to create, retrieve
105  * and delete cache entries related to the SSL session.
106  *
107  * @param[in] request The current request.
108  * @param[in] session_id Identifier for the session.
109  */
110 static inline CC_HINT(always_inline, nonnull(2))
111 void tls_cache_session_id_to_vp(request_t *request, uint8_t const *session_id)
112 {
113  fr_pair_t *vp;
115  fr_pair_value_memdup_buffer(vp, session_id, true);
116 }
117 
118 static inline CC_HINT(always_inline, nonnull(2))
119 void _tls_cache_load_state_reset(request_t *request, fr_tls_cache_t *cache, char const *func)
120 {
121  if (cache->load.sess) {
123  SESSION_ID(sess_id, cache->load.sess);
124  ROPTIONAL(RDEBUG3, DEBUG3, "Session ID %pV - Freeing loaded session in %s", &sess_id, func);
125  }
126 
127  SSL_SESSION_free(cache->load.sess);
128  cache->load.sess = NULL;
129  }
130  cache->load.state = FR_TLS_CACHE_LOAD_INIT;
131 }
132 #define tls_cache_load_state_reset(_request, _cache) _tls_cache_load_state_reset(_request, _cache, __FUNCTION__)
133 
134 static inline CC_HINT(always_inline, nonnull(2))
135 void _tls_cache_store_state_reset(request_t *request, fr_tls_cache_t *cache, char const *func)
136 {
137  if (cache->store.sess) {
139  SESSION_ID(sess_id, cache->store.sess);
140  ROPTIONAL(RDEBUG3, DEBUG3, "Session ID %pV - Freeing session to store in %s", &sess_id, func);
141  }
142  SSL_SESSION_free(cache->store.sess);
143  cache->store.sess = NULL;
144  }
145  cache->store.state = FR_TLS_CACHE_STORE_INIT;
146 }
147 #define tls_cache_store_state_reset(_request, _cache) _tls_cache_store_state_reset(_request, _cache, __FUNCTION__)
148 
149 static inline CC_HINT(always_inline)
150 void _tls_cache_clear_state_reset(request_t *request, fr_tls_cache_t *cache, char const *func)
151 {
152  if (cache->clear.id) {
154  ROPTIONAL(RDEBUG3, DEBUG3, "Session ID %pV - Freeing session ID to clear in %s",
155  fr_box_octets_buffer(cache->clear.id), func);
156  TALLOC_FREE(cache->clear.id);
157  }
158  }
159  cache->clear.state = FR_TLS_CACHE_CLEAR_INIT;
160 }
161 #define tls_cache_clear_state_reset(_request, _cache) _tls_cache_clear_state_reset(_request, _cache, __FUNCTION__)
162 
163 /** Serialize the session-state list and store it in the SSL_SESSION *
164  *
165  */
166 static int tls_cache_app_data_set(request_t *request, SSL_SESSION *sess)
167 {
168  fr_dbuff_t dbuff;
169  fr_dbuff_uctx_talloc_t tctx;
170  fr_dcursor_t dcursor;
171  fr_pair_t *vp;
172  ssize_t slen;
173  int ret;
174 
175  if (RDEBUG_ENABLED2) {
176  SESSION_ID(sess_id, sess);
177 
178  RDEBUG2("Session ID %pV - Adding &session-state[*] to data", &sess_id);
179  RINDENT();
180  log_request_pair_list(L_DBG_LVL_2, request, NULL, &request->session_state_pairs, NULL);
181  REXDENT();
182  }
183 
184  /*
185  * Absolute maximum is `0..2^16-1`.
186  *
187  * We leave OpenSSL 2k to add anything else
188  */
189  MEM(fr_dbuff_init_talloc(NULL, &dbuff, &tctx, 1024, 1024 * 62));
190 
191  /*
192  * Encode the session-state contents and
193  * add it to the ticket.
194  */
195  for (vp = fr_pair_dcursor_init(&dcursor, &request->session_state_pairs);
196  vp;
197  vp = fr_dcursor_current(&dcursor)) {
198  slen = fr_internal_encode_pair(&dbuff, &dcursor, NULL);
199  if (slen < 0) {
200  SESSION_ID(sess_id, sess);
201 
202  RPERROR("Session ID %pV - Failed serialising session-state list", &sess_id);
203  fr_dbuff_free_talloc(&dbuff);
204  return 0;
205  }
206  }
207 
208  RHEXDUMP4(fr_dbuff_start(&dbuff), fr_dbuff_used(&dbuff), "session-ticket application data");
209 
210  /*
211  * Pass the serialized session-state list
212  * over to OpenSSL.
213  */
214  ret = SSL_SESSION_set1_ticket_appdata(sess, fr_dbuff_start(&dbuff), fr_dbuff_used(&dbuff));
215  fr_dbuff_free_talloc(&dbuff); /* OpenSSL memdups the data */
216  if (ret != 1) {
217  SESSION_ID(sess_id, sess);
218 
219  fr_tls_log(request, "Session ID %pV - Failed setting application data", &sess_id);
220  return -1;
221  }
222 
223  return 0;
224 }
225 
226 static int tls_cache_app_data_get(request_t *request, SSL_SESSION *sess)
227 {
228  uint8_t *data;
229  size_t data_len;
230  fr_dbuff_t dbuff;
231  fr_pair_list_t tmp;
232 
233  /*
234  * Extract the session-state list from the ticket.
235  */
236  if (SSL_SESSION_get0_ticket_appdata(sess, (void **)&data, &data_len) != 1) {
237  SESSION_ID(sess_id, sess);
238 
239  fr_tls_log(request, "Session ID %pV - Failed retrieving application data", &sess_id);
240  return -1;
241  }
242 
243  fr_pair_list_init(&tmp);
244  fr_dbuff_init(&dbuff, data, data_len);
245 
246  RHEXDUMP4(fr_dbuff_start(&dbuff), fr_dbuff_len(&dbuff), "session application data");
247 
248  /*
249  * Decode the session-state data into a temporary list.
250  *
251  * It's very important that we decode _all_ attributes,
252  * or disallow session resumption.
253  */
254  while (fr_dbuff_remaining(&dbuff) > 0) {
255  if (fr_internal_decode_pair_dbuff(request->session_state_ctx, &tmp,
256  fr_dict_root(request->dict), &dbuff, NULL) < 0) {
257  SESSION_ID(sess_id, sess);
258 
259  fr_pair_list_free(&tmp);
260  RPEDEBUG("Session-ID %pV - Failed decoding session-state", &sess_id);
261  return -1;
262  }
263  }
264 
265  if (RDEBUG_ENABLED2) {
266  SESSION_ID(sess_id, sess);
267 
268  RDEBUG2("Session-ID %pV - Restoring &session-state[*]", &sess_id);
269  RINDENT();
270  log_request_pair_list(L_DBG_LVL_2, request, NULL, &tmp, "&session-state.");
271  REXDENT();
272  }
273 
274  fr_pair_list_append(&request->session_state_pairs, &tmp);
275 
276  return 0;
277 }
278 
279 /** Delete session data be deleted from the cache
280  *
281  * @param[in] sess to be deleted.
282  */
283 static void tls_cache_delete_request(SSL_SESSION *sess)
284 {
285  fr_tls_session_t *tls_session;
286  fr_tls_cache_t *tls_cache;
287  request_t *request;
288 
289  tls_session = talloc_get_type_abort(SSL_SESSION_get_ex_data(sess, FR_TLS_EX_INDEX_TLS_SESSION), fr_tls_session_t);
290 
291  if (!tls_session->cache) return;
292 
293  request = fr_tls_session_request(tls_session->ssl);
294  tls_cache = tls_session->cache;
295 
296  /*
297  * Request was cancelled just return without doing any work.
298  */
299  if (unlang_request_is_cancelled(request)) return;
300 
301  fr_assert(tls_cache->clear.state == FR_TLS_CACHE_CLEAR_INIT);
302 
303  /*
304  * Record the session to delete
305  */
306  tls_cache->clear.id = fr_tls_cache_id(tls_cache, sess);
307  if (!tls_cache->clear.id) {
308  RWDEBUG("Error retrieving Session ID");
309  return;
310  }
311 
312  RDEBUG3("Session ID %pV - Requested session clear", fr_box_octets_buffer(tls_cache->clear.id));
313 
314  tls_cache->clear.state = FR_TLS_CACHE_CLEAR_REQUESTED;
315 
316  /*
317  * We store a copy of the pointer for the session
318  * in tls_session->session. If the session is
319  * being freed then this pointer must be invalid
320  * so clear it to prevent crashes in other areas
321  * of the code.
322  */
323  if (tls_session->session == sess) tls_session->session = NULL;
324 
325  /*
326  * Previously the code called ASYNC_pause_job();
327  * assuming this callback would always be called
328  * from SSL_read() or another SSL function.
329  *
330  * Unfortunately it appears that the call path
331  * can also be triggered with SSL_CTX_remove_session
332  * if the reference count on the SSL_SESSION
333  * drops to zero.
334  *
335  * We now check the 'can_pause' flag to determine
336  * if we're inside a yieldable SSL_read call.
337  */
338  if (tls_session->can_pause) ASYNC_pause_job();
339 }
340 
341 /** Process the result of `session load { ... }`
342  */
343 static unlang_action_t tls_cache_load_result(UNUSED rlm_rcode_t *p_result, UNUSED int *priority,
344  request_t *request, void *uctx)
345 {
346  fr_tls_session_t *tls_session = talloc_get_type_abort(uctx, fr_tls_session_t);
347  fr_tls_cache_t *tls_cache = tls_session->cache;
348  fr_pair_t *vp;
349  uint8_t const *q, **p;
350  SSL_SESSION *sess;
351 
352  vp = fr_pair_find_by_da(&request->reply_pairs, NULL, attr_tls_packet_type);
353  if (!vp || (vp->vp_uint32 != enum_tls_packet_type_success->vb_uint32)) {
354  RWDEBUG("Failed acquiring session data");
355  error:
356  tls_cache->load.state = FR_TLS_CACHE_LOAD_FAILED;
358  }
359 
360  vp = fr_pair_find_by_da(&request->reply_pairs, NULL, attr_tls_session_data);
361  if (!vp) {
362  RWDEBUG("No cached session found");
363  goto error;
364  }
365 
366  q = vp->vp_octets; /* openssl will mutate q, so we can't use vp_octets directly */
367  p = (unsigned char const **)&q;
368 
369  sess = d2i_SSL_SESSION(NULL, p, vp->vp_length);
370  if (!sess) {
371  fr_tls_log(request, "Failed loading persisted session");
372  goto error;
373  }
374 
375  if (RDEBUG_ENABLED3) {
376  SESSION_ID(sess_id, sess);
377 
378  RDEBUG3("Session ID %pV - Read %zu bytes of data. "
379  "Session de-serialized successfully", &sess_id, vp->vp_length);
380  SSL_SESSION_print(fr_tls_request_log_bio(request, L_DBG, L_DBG_LVL_3), sess);
381  }
382 
383  /*
384  * OpenSSL's API is very inconsistent.
385  *
386  * We need to set external data here, so it can be
387  * retrieved in fr_tls_cache_delete.
388  *
389  * ex_data is not serialised in i2d_SSL_SESSION
390  * so we don't have to bother unsetting it.
391  */
392  SSL_SESSION_set_ex_data(sess, FR_TLS_EX_INDEX_TLS_SESSION, fr_tls_session(tls_session->ssl));
393 
394  tls_cache->load.state = FR_TLS_CACHE_LOAD_RETRIEVED;
395  tls_cache->load.sess = sess; /* This is consumed in tls_cache_load_cb */
396 
398 }
399 
400 /** Push a `session load { ... }` call into the current request, using a subrequest
401  *
402  * @param[in] request The current request.
403  * @Param[in] tls_session The current TLS session.
404  * @return
405  * - UNLANG_ACTION_CALCULATE_RESULT on noop.
406  * - UNLANG_ACTION_PUSHED_CHILD on success.
407  * - UNLANG_ACTION_FAIL on failure.
408  */
409 static unlang_action_t tls_cache_load_push(request_t *request, fr_tls_session_t *tls_session)
410 {
411  fr_tls_cache_t *tls_cache = tls_session->cache;
412  fr_tls_conf_t *conf = fr_tls_session_conf(tls_session->ssl);
413  request_t *child;
414  fr_pair_t *vp;
415  unlang_action_t ua;
416 
417  if (tls_cache->load.state != FR_TLS_CACHE_LOAD_REQUESTED) return UNLANG_ACTION_CALCULATE_RESULT;
418 
419  fr_assert(tls_cache->load.id);
420 
421  MEM(child = unlang_subrequest_alloc(request, dict_tls));
422  request = child;
423 
424  /*
425  * Setup the child request for loading
426  * session resumption data.
427  */
429  vp->vp_uint32 = enum_tls_packet_type_load_session->vb_uint32;
430 
431  /*
432  * Add the session identifier we're
433  * trying to load.
434  */
435  tls_cache_session_id_to_vp(child, tls_cache->load.id);
436 
437  /*
438  * Allocate a child, and set it up to call
439  * the TLS virtual server.
440  */
441  ua = fr_tls_call_push(child, tls_cache_load_result, conf, tls_session);
442  if (ua < 0) {
443  talloc_free(child);
444  tls_cache_load_state_reset(request, tls_cache);
445  return UNLANG_ACTION_FAIL;
446  }
447 
448  return ua;
449 }
450 
451 /** Process the result of `session store { ... }`
452  */
453 static unlang_action_t tls_cache_store_result(UNUSED rlm_rcode_t *p_result, UNUSED int *priority,
454  request_t *request, void *uctx)
455 {
456  fr_tls_session_t *tls_session = talloc_get_type_abort(uctx, fr_tls_session_t);
457  fr_tls_cache_t *tls_cache = tls_session->cache;
458  fr_pair_t *vp;
459 
460  tls_cache_store_state_reset(request, tls_cache);
461 
462  vp = fr_pair_find_by_da(&request->reply_pairs, NULL, attr_tls_packet_type);
463  if (vp && (vp->vp_uint32 == enum_tls_packet_type_success->vb_uint32)) {
464  tls_cache->store.state = FR_TLS_CACHE_STORE_PERSISTED; /* Avoid spurious clear calls */
465  } else {
466  RWDEBUG("Failed storing session data");
467  tls_cache->store.state = FR_TLS_CACHE_STORE_INIT;
468  }
469 
471 }
472 
473 /** Push a `session store { ... }` call into the current request, using a subrequest
474  *
475  * @param[in] request The current request.
476  * @param[in] conf TLS configuration.
477  * @Param[in] tls_session The current TLS session.
478  * @return
479  * - UNLANG_ACTION_CALCULATE_RESULT on noop.
480  * - UNLANG_ACTION_PUSHED_CHILD on success.
481  * - UNLANG_ACTION_FAIL on failure.
482  */
483 static inline CC_HINT(always_inline)
484 unlang_action_t tls_cache_store_push(request_t *request, fr_tls_conf_t *conf, fr_tls_session_t *tls_session)
485 {
486  fr_tls_cache_t *tls_cache = tls_session->cache;
487  size_t len, ret;
488 
489  uint8_t *p, *data = NULL;
490 
491  request_t *child;
492  fr_pair_t *vp;
493  SSL_SESSION *sess = tls_session->cache->store.sess;
494  unlang_action_t ua;
495  fr_time_t expires = fr_time_from_sec((time_t)(SSL_SESSION_get_time(sess) + SSL_get_timeout(sess)));
496  fr_time_t now = fr_time();
497 
498  fr_assert(tls_cache->store.sess);
499  fr_assert(tls_cache->store.state == FR_TLS_CACHE_STORE_REQUESTED);
500 
501  if (fr_time_lteq(expires, now)) {
502  fr_value_box_t id;
503  fr_tls_cache_id_to_box_shallow(&id, sess);
504 
505  RWDEBUG("Session ID %pV - Session has already expired, not storing", &id);
507  }
508 
509  /*
510  * Add the current session-state list
511  * contents to the ssl-data
512  */
513  if (tls_cache_app_data_set(request, sess) < 0) return UNLANG_ACTION_FAIL;
514 
515  MEM(child = unlang_subrequest_alloc(request, dict_tls));
516  request = child;
517 
518  /*
519  * Setup the child request for storing
520  * session resumption data.
521  */
523  vp->vp_uint32 = enum_tls_packet_type_store_session->vb_uint32;
524 
525  /*
526  * Add the session identifier we're trying
527  * to store.
528  */
530  fr_pair_value_memdup_buffer_shallow(vp, fr_tls_cache_id(vp, sess), true);
531 
532  /*
533  * How long the session has to live
534  */
536  vp->vp_time_delta = fr_time_sub(expires, now);
537 
538  /*
539  * Serialize the session
540  */
541  len = i2d_SSL_SESSION(sess, NULL); /* find out what length data we need */
542  if (len < 1) {
543  fr_value_box_t id;
544  fr_tls_cache_id_to_box_shallow(&id, sess);
545 
546  /* something went wrong */
547  fr_tls_strerror_printf(NULL); /* Drain the OpenSSL error stack */
548  RPWDEBUG("Session ID %pV - Serialisation failed, couldn't determine "
549  "required buffer length", &id);
550  error:
551  tls_cache_store_state_reset(request, tls_cache);
552  talloc_free(child);
553  return UNLANG_ACTION_FAIL;
554  }
555 
557  MEM(data = talloc_array(vp, uint8_t, len));
558 
559  /* openssl mutates &p */
560  p = data;
561  ret = i2d_SSL_SESSION(sess, &p); /* Serialize as ASN.1 */
562  if (ret != len) {
563  fr_value_box_t id;
564  fr_tls_cache_id_to_box_shallow(&id, sess);
565 
566  fr_tls_strerror_printf(NULL); /* Drain the OpenSSL error stack */
567  RPWDEBUG("Session ID %pV - Serialisation failed", &id);
568  talloc_free(data);
569  goto error;
570  }
572 
573  /*
574  * Allocate a child, and set it up to call
575  * the TLS virtual server.
576  */
577  ua = fr_tls_call_push(child, tls_cache_store_result, conf, tls_session);
578  if (ua < 0) goto error;
579 
580  return ua;
581 }
582 
583 /** Process the result of `session clear { ... }`
584  */
585 static unlang_action_t tls_cache_clear_result(UNUSED rlm_rcode_t *p_result, UNUSED int *priority,
586  request_t *request, void *uctx)
587 {
588  fr_tls_session_t *tls_session = talloc_get_type_abort(uctx, fr_tls_session_t);
589  fr_tls_cache_t *tls_cache = tls_session->cache;
590  fr_pair_t *vp;
591 
592  tls_cache_clear_state_reset(request, tls_cache);
593 
594  vp = fr_pair_find_by_da(&request->reply_pairs, NULL, attr_tls_packet_type);
595  if (vp &&
596  ((vp->vp_uint32 == enum_tls_packet_type_success->vb_uint32) ||
597  (vp->vp_uint32 == enum_tls_packet_type_notfound->vb_uint32))) {
599  }
600 
601  RWDEBUG("Failed deleting session data - security may be compromised");
603 }
604 
605 /** Push a `session clear { ... }` call into the current request, using a subrequest
606  *
607  * @param[in] request The current request.
608  * @param[in] conf TLS configuration.
609  * @Param[in] tls_session The current TLS session.
610  * @return
611  * - UNLANG_ACTION_CALCULATE_RESULT on noop.
612  * - UNLANG_ACTION_PUSHED_CHILD on success.
613  * - UNLANG_ACTION_FAIL on failure.
614  */
615 static inline CC_HINT(always_inline)
616 unlang_action_t tls_cache_clear_push(request_t *request, fr_tls_conf_t *conf, fr_tls_session_t *tls_session)
617 {
618  request_t *child;
619  fr_pair_t *vp;
620  fr_tls_cache_t *tls_cache = tls_session->cache;
621  unlang_action_t ua;
622 
623  fr_assert(tls_cache->clear.state == FR_TLS_CACHE_CLEAR_REQUESTED);
624  fr_assert(tls_cache->clear.id);
625 
626  MEM(child = unlang_subrequest_alloc(request, dict_tls));
627  request = child;
628 
629  /*
630  * Setup the child request for loading
631  * session resumption data.
632  */
634  vp->vp_uint32 = enum_tls_packet_type_clear_session->vb_uint32;
635 
636  /*
637  * Add the session identifier we're
638  * trying to load.
639  */
640  tls_cache_session_id_to_vp(child, tls_cache->clear.id);
641 
642  /*
643  * Allocate a child, and set it up to call
644  * the TLS virtual server.
645  */
646  ua = fr_tls_call_push(child, tls_cache_clear_result, conf, tls_session);
647  if (ua < 0) {
648  talloc_free(child);
649  tls_cache_clear_state_reset(request, tls_cache);
650  return UNLANG_ACTION_FAIL;
651  }
652 
653  return ua;
654 }
655 
656 /** Push a `session store { ... }` or session clear { ... }` or `session load { ... }` depending on what operations are pending
657  *
658  * @param[in] request The current request.
659  * @Param[in] tls_session The current TLS session.
660  * @return
661  * - UNLANG_ACTION_CALCULATE_RESULT - No pending actions
662  * - UNLANG_ACTION_PUSHED_CHILD - Pending operations to evaluate.
663  */
664 unlang_action_t fr_tls_cache_pending_push(request_t *request, fr_tls_session_t *tls_session)
665 {
666  fr_tls_cache_t *tls_cache = tls_session->cache;
667  fr_tls_conf_t *conf = fr_tls_session_conf(tls_session->ssl);
668 
669  if (!tls_cache) return UNLANG_ACTION_CALCULATE_RESULT; /* No caching allowed */
670 
671  /*
672  * Load stateful session data
673  */
674  if (tls_cache->load.state == FR_TLS_CACHE_LOAD_REQUESTED) {
675  return tls_cache_load_push(request, tls_session);
676  }
677 
678  /*
679  * We only support a single session
680  * ticket currently...
681  */
682  if (tls_cache->clear.state == FR_TLS_CACHE_CLEAR_REQUESTED) {
683  /*
684  * Abort any pending store operations
685  * if they were for the same ID as
686  * we're now trying to clear.
687  */
688  if (tls_cache->store.state == FR_TLS_CACHE_STORE_REQUESTED) {
689  unsigned int len;
690  uint8_t const *id;
691 
692  id = SSL_SESSION_get_id(tls_cache->store.sess, &len);
693  if ((len == talloc_array_length(tls_cache->clear.id)) &&
694  (memcmp(tls_cache->clear.id, id, len) == 0)) {
695  tls_cache_store_state_reset(request, tls_cache);
696  }
697  }
698 
699  return tls_cache_clear_push(request, conf, tls_session);
700  }
701 
702  if (tls_cache->store.state == FR_TLS_CACHE_STORE_REQUESTED) {
703  return tls_cache_store_push(request, conf, tls_session);
704  }
705 
707 }
708 
709 /** Write a newly created session data to the tls_session->cache structure
710  *
711  * @note If you hit an assert in this function, it was likely called twice, which shouldn't happen
712  * so blame OpenSSL.
713  *
714  * @param[in] ssl session state.
715  * @param[in] sess to serialise and write to the cache.
716  * @return
717  * - 1. What we return is not used by OpenSSL to indicate success
718  * or failure, but to indicate whether it should free its copy of
719  * the session data.
720  * In this case we tell it not to free the session data, as we
721  */
722 static int tls_cache_store_cb(SSL *ssl, SSL_SESSION *sess)
723 {
724  request_t *request;
725  fr_tls_session_t *tls_session;
726  fr_tls_cache_t *tls_cache;
727  unsigned int id_len;
728  uint8_t const *id;
729 
730  /*
731  * This functions should only be called once during the lifetime
732  * of the tls_session, as the fields aren't re-populated on
733  * resumption.
734  */
735  tls_session = fr_tls_session(ssl);
736  request = fr_tls_session_request(tls_session->ssl);
737  tls_cache = tls_session->cache;
738 
739  /*
740  * Request was cancelled, just get OpenSSL to
741  * free the session data, and don't do any work.
742  */
743  if (unlang_request_is_cancelled(request)) return 0;
744 
745  id = SSL_SESSION_get_id(sess, &id_len);
746  RDEBUG3("Session ID %pV - Requested store", fr_box_octets(id, id_len));
747  /*
748  * Store the session blob and session id for writing
749  * later, once all the authentication phases have completed.
750  */
751  tls_cache->store.sess = sess;
752  tls_cache->store.state = FR_TLS_CACHE_STORE_REQUESTED;
753 
754  return 1;
755 }
756 
757 /** Read session data from the cache
758  *
759  * @param[in] ssl session state.
760  * @param[in] key to retrieve session data for.
761  * @param[in] key_len The length of the key.
762  * @param[out] copy Indicates whether OpenSSL should increment the reference
763  * count on SSL_SESSION to prevent it being automatically freed. We always
764  * set this to 0.
765  * @return
766  * - Deserialised session data on success.
767  * - NULL on error.
768  */
769 static SSL_SESSION *tls_cache_load_cb(SSL *ssl,
770  unsigned char const *key,
771  int key_len, int *copy)
772 {
773  fr_tls_session_t *tls_session;
774  fr_tls_cache_t *tls_cache;
775  request_t *request;
776 
777  tls_session = fr_tls_session(ssl);
778  request = fr_tls_session_request(tls_session->ssl);
779  tls_cache = tls_session->cache;
780 
781  /*
782  * Request was cancelled, don't return any session and hopefully
783  * OpenSSL will return back to SSL_read() soon.
784  */
785  if (unlang_request_is_cancelled(request)) return NULL;
786 
787  /*
788  * Ensure if session resumption is disallowed this callback
789  * will never return session data.
790  */
791  if (!tls_cache || !tls_session->allow_session_resumption) return NULL;
792 
793  /*
794  * 1. On the first call we return SSL_magic_pending_session_ptr.
795  * This causes the current SSL_read() call to error out and
796  * for SSL_get_error() to return SSL_ERROR_PENDING_SESSION.
797  * 2. On receiving SSL_ERROR_PENDING_SESSION we asynchronously
798  * load session information from a datastore and associated
799  * it with the SSL session.
800  * 3. We asynchronously validate the certificate information
801  * retrieved during the session session load.
802  * 3. We call SSL_read() again, which in turn calls this callback
803  * again.
804  */
805 again:
806  switch (tls_cache->load.state) {
807  case FR_TLS_CACHE_LOAD_INIT:
808  fr_assert(!tls_cache->load.id);
809 
810  tls_cache->load.state = FR_TLS_CACHE_LOAD_REQUESTED;
811  MEM(tls_cache->load.id = talloc_typed_memdup(tls_cache, (uint8_t const *)key, key_len));
812 
813  RDEBUG3("Requested session load - ID %pV", fr_box_octets_buffer(tls_cache->load.id));
814 
815  /*
816  * Cache functions are only allowed during the handshake
817  * FIXME: With TLS 1.3 session tickets can be sent
818  * later... Technically every point where we call
819  * SSL_read() may need to be a yield point.
820  */
821  if (unlikely(!tls_session->can_pause)) {
822  cant_pause:
823  fr_assert_msg("Unexpected call to %s. "
824  "tls_session_async_handshake_cont must be in call stack", __FUNCTION__);
825  return NULL;
826  }
827  /*
828  * Jumps back to SSL_read() in session.c
829  *
830  * Be aware that if the request is cancelled
831  * whatever was meant to be done during the
832  * time we yielded may not have been completed.
833  */
834  ASYNC_pause_job();
835 
836  /*
837  * load cache { ... } returned, but the parent
838  * request was cancelled, try and get everything
839  * back into a consistent state and tell OpenSSL
840  * we failed to load the session.
841  */
842  if (unlang_request_is_cancelled(request)) {
843  tls_cache_load_state_reset(request, tls_cache); /* Clears any loaded session data */
844  return NULL;
845 
846  }
847  goto again;
848 
849  case FR_TLS_CACHE_LOAD_REQUESTED:
850  fr_assert(0); /* Called twice without attempting the load?! */
851  tls_cache->load.state = FR_TLS_CACHE_LOAD_FAILED;
852  break;
853 
854  case FR_TLS_CACHE_LOAD_RETRIEVED:
855  {
856  SSL_SESSION *sess;
857 
858  TALLOC_FREE(tls_cache->load.id);
859 
860  RDEBUG3("Setting session data");
861 
862  /*
863  * This restores the contents of &session-state[*]
864  * which hopefully still contains all the certificate
865  * pairs.
866  *
867  * Although the SSL_SESSION does contain a copy of
868  * the peer's certificate, it does not contain the
869  * peer's certificate chain, and so isn't reliable
870  * for performing re-validation.
871  */
872  if (tls_cache_app_data_get(request, tls_cache->load.sess) < 0) {
873  REDEBUG("Denying session resumption via session-id");
874  verify_error:
875  /*
876  * Request the session be deleted the next
877  * time something calls cache action pending.
878  */
879  tls_cache_delete_request(tls_cache->load.sess);
880  tls_cache_load_state_reset(request, tls_session->cache); /* Free the session */
881  return NULL;
882  }
883 
884  /*
885  * This sets the validation state of the tls_session
886  * so that when we call ASYNC_pause_job(), and execution
887  * jumps back to tls_session_async_handshake_cont
888  * (just under SSL_read())
889  * the code there knows what job it needs to push onto
890  * the unlang stack.
891  */
892  fr_tls_verify_cert_request(tls_session, true);
893 
894  if (unlikely(!tls_session->can_pause)) goto cant_pause;
895  /*
896  * Jumps back to SSL_read() in session.c
897  *
898  * Be aware that if the request is cancelled
899  * whatever was meant to be done during the
900  * time we yielded may not have been completed.
901  */
902  ASYNC_pause_job();
903 
904  /*
905  * Certificate validation returned but the request
906  * was cancelled. Free any data we have so far
907  * and reset the states, then let OpenSSL know
908  * we failed to load the session.
909  */
910  if (unlang_request_is_cancelled(request)) {
911  tls_cache_load_state_reset(request, tls_cache); /* Clears any loaded session data */
912  fr_tls_verify_cert_reset(tls_session);
913  return NULL;
914 
915  }
916 
917  /*
918  * If we couldn't validate the client certificate
919  * then validation overall fails.
920  */
921  if (!fr_tls_verify_cert_result(tls_session)) {
922  RDEBUG2("Certificate re-validation failed, denying session resumption via session-id");
923  goto verify_error;
924  }
925  sess = tls_cache->load.sess;
926 
927  /*
928  * After we return it's OpenSSL's responsibility
929  * to free the session data, so set our copy of
930  * the pointer to NULL, to prevent a double free
931  * on cleanup.
932  */
933  {
934  SESSION_ID(sess_id, tls_cache->load.sess);
935 
936  RDEBUG3("Session ID %pV - Session ownership transferred to libssl", &sess_id);
937  *copy = 0;
938  tls_cache->load.sess = NULL;
939  }
940  return sess;
941  }
942 
943 
944  case FR_TLS_CACHE_LOAD_FAILED:
945  RDEBUG3("Session data load failed");
946  break;
947  }
948 
949  TALLOC_FREE(tls_cache->load.id);
950  fr_assert(!tls_cache->load.sess);
951 
952  return NULL;
953 }
954 
955 /** Delete session data from the cache
956  *
957  * @param[in] ctx Current ssl context.
958  * @param[in] sess to be deleted.
959  */
960 static void tls_cache_delete_cb(UNUSED SSL_CTX *ctx, SSL_SESSION *sess)
961 {
962  /*
963  * Not sure why this happens, but sometimes SSL_SESSION *s
964  * make it here without the correct ex data.
965  *
966  * Maybe it's one OpenSSL created internally?
967  */
968  if (!SSL_SESSION_get_ex_data(sess, FR_TLS_EX_INDEX_TLS_SESSION)) return;
969  tls_cache_delete_request(sess);
970 }
971 
972 /** Prevent a TLS session from being resumed in future
973  *
974  * @note In OpenSSL > 1.1.0 this should not be called directly, but passed as a callback to
975  * SSL_CTX_set_not_resumable_session_callback.
976  *
977  * @param ssl The current OpenSSL session.
978  * @param is_forward_secure Whether the cipher is forward secure, pass -1 if unknown.
979  * @return
980  * - 0 if session-resumption is allowed.
981  * - 1 if enabling session-resumption was disabled for this session.
982  */
983 int fr_tls_cache_disable_cb(SSL *ssl, int is_forward_secure)
984 {
985  request_t *request;
986 
987  fr_tls_session_t *tls_session;
988  fr_pair_t *vp;
989 
990  tls_session = fr_tls_session(ssl);
991  request = fr_tls_session_request(tls_session->ssl);
992 
993  /*
994  * Request was cancelled, try and get OpenSSL to
995  * do as little work as possible.
996  */
997  if (unlang_request_is_cancelled(request)) return 1;
998 
999  {
1000  fr_tls_conf_t *conf;
1001 
1002  conf = talloc_get_type_abort(SSL_get_ex_data(ssl, FR_TLS_EX_INDEX_CONF), fr_tls_conf_t);
1003  if (conf->cache.require_extms && (SSL_get_extms_support(tls_session->ssl) == 0)) {
1004  RDEBUG2("Client does not support the Extended Master Secret extension, "
1005  "denying session resumption");
1006  goto disable;
1007  }
1008 
1009  if (conf->cache.require_pfs && !is_forward_secure) {
1010  RDEBUG2("Cipher suite is not forward secure, denying session resumption");
1011  goto disable;
1012  }
1013  }
1014 
1015  /*
1016  * If there's no session resumption, delete the entry
1017  * from the cache. This means either it's disabled
1018  * globally for this SSL context, OR we were told to
1019  * disable it for this user.
1020  *
1021  * This also means you can't turn it on just for one
1022  * user.
1023  */
1024  if (!tls_session->allow_session_resumption) {
1025  RDEBUG2("Session resumption not enabled for this TLS session, denying session resumption");
1026  goto disable;
1027  }
1028 
1029  vp = fr_pair_find_by_da(&request->control_pairs, NULL, attr_allow_session_resumption);
1030  if (vp && (vp->vp_uint32 == 0)) {
1031  RDEBUG2("&control.Allow-Session-Resumption == no, denying session resumption");
1032  disable:
1033  SSL_CTX_remove_session(tls_session->ctx, tls_session->session);
1034  tls_session->allow_session_resumption = false;
1035  return 1;
1036  }
1037 
1038  RDEBUG2("Allowing future session-resumption");
1039 
1040  return 0;
1041 }
1042 
1043 /** Prevent a pending TLS session being persisted, and clear any resumed sessions
1044  *
1045  * Usually called if authentication has failed for some reason.
1046  *
1047  * Will clear any serialized data out of the tls_session structure
1048  * and should result in tls_cache_delete_cb being called.
1049  *
1050  * @note Calling this function will immediately free the memory used
1051  * by the session, but not the external persisted copy of the
1052  * session. To clear the persisted copy #fr_tls_cache_pending_push
1053  * must be called in a place where the caller is prepared to yield.
1054  * In most cases this means whether the handshake is a success or
1055  * failure, the last thing the caller of the TLS code should do
1056  * is set the result, and call #fr_tls_cache_pending_push.
1057  *
1058  * @param[in] request to use for running any async cache actions.
1059  * @param[in] tls_session on which to prevent resumption.
1060  */
1061 void fr_tls_cache_deny(request_t *request, fr_tls_session_t *tls_session)
1062 {
1063  fr_tls_cache_t *tls_cache = tls_session->cache;
1064  bool tmp_bind = !fr_tls_session_request_bound(tls_session->ssl);
1065 
1066  /*
1067  * This is necessary to allow this function to
1068  * be called inside and outside of OpenSSL handshake
1069  * code.
1070  */
1071  if (tmp_bind) {
1072  fr_tls_session_request_bind(tls_session->ssl, request);
1073  /*
1074  * If there's already a request bound, it better be
1075  * the one passed to this function.
1076  */
1077  } else {
1078  fr_assert(fr_tls_session_request(tls_session->ssl) == request);
1079  }
1080 
1081  /*
1082  * SSL_CTX_remove_session frees the previously loaded
1083  * session in tls_session. If the reference count reaches zero
1084  * the SSL_CTX_sess_remove_cb is called, which in our code is
1085  * tls_cache_delete_cb.
1086  *
1087  * tls_cache_delete_cb calls tls_cache_delete_request
1088  * to record the ID of tls_session->session
1089  * in our pending cache state structure.
1090  *
1091  * tls_cache_delete_request does NOT immediately call the
1092  * `cache clear {}` section as that must be done in a code area
1093  * which is prepared to yield.
1094  *
1095  * #fr_tls_cache_pending_push MUST be called to actually
1096  * clear external data.
1097  */
1098  if (tls_session->session) SSL_CTX_remove_session(tls_session->ctx, tls_session->session);
1099  tls_session->allow_session_resumption = false;
1100 
1101  /*
1102  * Clear any pending store requests.
1103  */
1104  tls_cache_store_state_reset(fr_tls_session_request(tls_session->ssl), tls_cache);
1105 
1106  /*
1107  * Unbind the request last...
1108  */
1109  if (tmp_bind) fr_tls_session_request_unbind(tls_session->ssl);
1110 }
1111 
1112 /** Cleanup any memory allocated by OpenSSL
1113  */
1114 static int _tls_cache_free(fr_tls_cache_t *tls_cache)
1115 {
1116  tls_cache_load_state_reset(NULL, tls_cache);
1117  tls_cache_store_state_reset(NULL, tls_cache);
1118 
1119  return 0;
1120 }
1121 
1122 /** Allocate a session cache state structure, and assign it to a tls_session
1123  *
1124  * @note This must be called if session caching is enabled for a tls session.
1125  *
1126  * @param[in] tls_session to assign cache structure to.
1127  */
1128 void fr_tls_cache_session_alloc(fr_tls_session_t *tls_session)
1129 {
1130  fr_assert(!tls_session->cache);
1131 
1132  MEM(tls_session->cache = talloc_zero(tls_session, fr_tls_cache_t));
1133  talloc_set_destructor(tls_session->cache, _tls_cache_free);
1134 }
1135 
1136 /** Disable stateless session tickets for a given TLS ctx
1137  *
1138  * @param[in] ctx to disable session tickets for.
1139  */
1140 static inline CC_HINT(always_inline)
1141 void tls_cache_disable_stateless_resumption(SSL_CTX *ctx)
1142 {
1143  long ctx_options = SSL_CTX_get_options(ctx);
1144 
1145  /*
1146  * Disable session tickets for older TLS versions
1147  */
1148  ctx_options |= SSL_OP_NO_TICKET;
1149  SSL_CTX_set_options(ctx, ctx_options);
1150 
1151 #if OPENSSL_VERSION_NUMBER >= 0x10101000L
1152  /*
1153  * This controls the number of stateful or stateless
1154  * tickets generated with TLS 1.3. In OpenSSL 1.1.0
1155  * it's also required to disable sending session tickets,
1156  * SSL_SESS_CACHE_OFF is not good enough.
1157  */
1158  SSL_CTX_set_num_tickets(ctx, 0);
1159 #endif
1160 }
1161 
1162 /** Disable stateful session resumption for a given TLS ctx
1163  *
1164  * @param[in] ctx to disable stateful session resumption for.
1165  */
1166 static inline CC_HINT(always_inline)
1167 void tls_cache_disable_statefull_resumption(SSL_CTX *ctx)
1168 {
1169  /*
1170  * Only disables stateful session-resumption.
1171  *
1172  * As per Matt Caswell:
1173  *
1174  * SSL_SESS_CACHE_OFF, when called on the server,
1175  * disables caching of server side sessions.
1176  * It does not switch off resumption. Resumption can
1177  * still occur if a stateless session ticket is used
1178  * (even in TLSv1.2).
1179  */
1180  SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
1181 }
1182 
1183 /** Called when new tickets are being generated
1184  *
1185  * This adds additional application data to the session ticket to
1186  * allow us to perform validation checks when the session is
1187  * resumed.
1188  */
1189 static int tls_cache_session_ticket_app_data_set(SSL *ssl, void *arg)
1190 {
1191  fr_tls_session_t *tls_session = fr_tls_session(ssl);
1192  fr_tls_cache_conf_t *tls_cache_conf = arg; /* Not talloced */
1193  SSL_SESSION *sess;
1194  request_t *request;
1195 
1196  /*
1197  * Check to see if we have a request bound
1198  * to the session. If we don't have a
1199  * request there's no application data to
1200  * add.
1201  */
1202  if (!fr_tls_session_request_bound(ssl)) return 1;
1203 
1204  /*
1205  * Encode the complete session state list
1206  * as app data. Then, when the session is
1207  * resumed, the session-state list is
1208  * repopulated.
1209  */
1210  request = fr_tls_session_request(ssl);
1211 
1212  /*
1213  * Request was cancelled, don't do anything.
1214  */
1215  if (unlang_request_is_cancelled(request)) return 0;
1216 
1217  /*
1218  * Fatal error - We definitely should be
1219  * attempting to generate session tickets
1220  * if it's not permitted.
1221  */
1222  if (!tls_session->allow_session_resumption ||
1223  (!(tls_cache_conf->mode & FR_TLS_CACHE_STATELESS))) {
1224  REDEBUG("Generating session-tickets is not allowed");
1225  return 0;
1226  }
1227 
1228  sess = SSL_get_session(ssl);
1229  if (!sess) {
1230  REDEBUG("Failed retrieving session in session generation callback");
1231  return 0;
1232  }
1233 
1234  if (tls_cache_app_data_set(request, sess) < 0) return 0;
1235 
1236  return 1;
1237 }
1238 
1239 /** Called when new tickets are being decoded
1240  *
1241  * This adds the session-state attributes back to the current request.
1242  */
1243 static SSL_TICKET_RETURN tls_cache_session_ticket_app_data_get(SSL *ssl, SSL_SESSION *sess,
1244  UNUSED unsigned char const *keyname,
1245  UNUSED size_t keyname_len,
1246  SSL_TICKET_STATUS status,
1247  void *arg)
1248 {
1249  fr_tls_session_t *tls_session = fr_tls_session(ssl);
1250  fr_tls_conf_t *conf = fr_tls_session_conf(tls_session->ssl);
1251  fr_tls_cache_conf_t *tls_cache_conf = arg; /* Not talloced */
1252  request_t *request = NULL;
1253 
1254  if (fr_tls_session_request_bound(ssl)) {
1255  request = fr_tls_session_request(ssl);
1256  if (unlang_request_is_cancelled(request)) return SSL_TICKET_RETURN_ABORT;
1257  }
1258 
1259  if (!tls_session->allow_session_resumption ||
1260  (!(tls_cache_conf->mode & FR_TLS_CACHE_STATELESS))) {
1261  ROPTIONAL(RDEBUG2, DEBUG2, "Session resumption not enabled for this TLS session, "
1262  "denying session resumption via session-ticket");
1263  return SSL_TICKET_RETURN_IGNORE;
1264  }
1265 
1266  switch (status) {
1267  case SSL_TICKET_EMPTY:
1268  case SSL_TICKET_NO_DECRYPT:
1269  case SSL_TICKET_FATAL_ERR_MALLOC:
1270  case SSL_TICKET_FATAL_ERR_OTHER:
1271  case SSL_TICKET_NONE:
1272 #ifdef STATIC_ANALYZER
1273  default:
1274 #endif
1275  return SSL_TICKET_RETURN_IGNORE_RENEW; /* Send a new ticket */
1276 
1277  case SSL_TICKET_SUCCESS:
1278  if (!request) return SSL_TICKET_RETURN_USE;
1279  break;
1280 
1281  case SSL_TICKET_SUCCESS_RENEW:
1282  if (!request) return SSL_TICKET_RETURN_USE_RENEW;
1283  break;
1284  }
1285 
1286  /*
1287  * This restores the contents of &session-state[*]
1288  * which hopefully still contains all the certificate
1289  * pairs.
1290  *
1291  * Although the SSL_SESSION does contain a copy of
1292  * the peer's certificate, it does not contain the
1293  * peer's certificate chain, and so isn't reliable
1294  * for performing re-validation.
1295  */
1296  if (tls_cache_app_data_get(request, sess) < 0) {
1297  REDEBUG("Denying session resumption via session-ticket");
1298  return SSL_TICKET_RETURN_IGNORE_RENEW;
1299  }
1300 
1301  if (conf->virtual_server && tls_session->verify_client_cert) {
1302  RDEBUG2("Requesting certificate re-validation for session-ticket");
1303  /*
1304  * This sets the validation state of the tls_session
1305  * so that when we call ASYNC_pause_job(), and execution
1306  * jumps back to tls_session_async_handshake_cont
1307  * (just under SSL_read())
1308  * the code there knows what job it needs to push onto
1309  * the unlang stack.
1310  */
1311  fr_tls_verify_cert_request(tls_session, true);
1312 
1313  /*
1314  * Cache functions are only allowed during the handshake
1315  * FIXME: With TLS 1.3 session tickets can be sent
1316  * later... Technically every point where we call
1317  * SSL_read() may need to be a yield point.
1318  */
1319  if (unlikely(!tls_session->can_pause)) {
1320  fr_assert_msg("Unexpected call to %s. "
1321  "tls_session_async_handshake_cont must be in call stack", __FUNCTION__);
1322  return SSL_TICKET_RETURN_IGNORE_RENEW;
1323  }
1324 
1325  /*
1326  * Jumps back to SSL_read() in session.c
1327  *
1328  * Be aware that if the request is cancelled
1329  * whatever was meant to be done during the
1330  * time we yielded may not have been completed.
1331  */
1332  ASYNC_pause_job();
1333 
1334  /*
1335  * If the request was cancelled get everything back into
1336  * a known state.
1337  */
1338  if (unlang_request_is_cancelled(request)) {
1339  fr_tls_verify_cert_reset(tls_session);
1340  return SSL_TICKET_RETURN_ABORT;
1341  }
1342 
1343  /*
1344  * If we couldn't validate the client certificate
1345  * give the client the opportunity to send a new
1346  * one, but _don't_ allow session resumption.
1347  */
1348  if (!fr_tls_verify_cert_result(tls_session)) {
1349  RDEBUG2("Certificate re-validation failed, denying session resumption via session-ticket");
1350  return SSL_TICKET_RETURN_IGNORE_RENEW;
1351  }
1352  }
1353 
1354  return (status == SSL_TICKET_SUCCESS_RENEW) ? SSL_TICKET_RETURN_USE_RENEW : SSL_TICKET_RETURN_USE;
1355 }
1356 
1357 /** Sets callbacks and flags on a SSL_CTX to enable/disable session resumption
1358  *
1359  * @param[in] ctx to modify.
1360  * @param[in] cache_conf Session caching configuration.
1361  * @return
1362  * - 0 on success.
1363  * - -1 on failure.
1364  */
1365 int fr_tls_cache_ctx_init(SSL_CTX *ctx, fr_tls_cache_conf_t const *cache_conf)
1366 {
1367  switch (cache_conf->mode) {
1368  case FR_TLS_CACHE_DISABLED:
1369  tls_cache_disable_stateless_resumption(ctx);
1370  tls_cache_disable_statefull_resumption(ctx);
1371  return 0;
1372 
1373  case FR_TLS_CACHE_AUTO:
1374  case FR_TLS_CACHE_STATEFUL:
1375  /*
1376  * Setup the callbacks for stateful session-resumption
1377  * i.e. where the server stores session information.
1378  */
1379  SSL_CTX_sess_set_new_cb(ctx, tls_cache_store_cb);
1380  SSL_CTX_sess_set_get_cb(ctx, tls_cache_load_cb);
1381  SSL_CTX_sess_set_remove_cb(ctx, tls_cache_delete_cb);
1382 
1383  /*
1384  * Controls the stateful cache mode
1385  *
1386  * Here we disable internal lookups, and rely on the
1387  * callbacks above.
1388  */
1389  SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER | SSL_SESS_CACHE_NO_INTERNAL);
1390 
1391  /*
1392  * Controls the validity period of the stateful cache.
1393  */
1394  SSL_CTX_set_timeout(ctx, fr_time_delta_to_sec(cache_conf->lifetime));
1395 
1396  /*
1397  * Disables stateless session tickets for TLS 1.3.
1398  */
1399  if (!(cache_conf->mode & FR_TLS_CACHE_STATELESS)) {
1400  tls_cache_disable_stateless_resumption(ctx);
1401  break;
1402  }
1403  FALL_THROUGH;
1404 
1405  case FR_TLS_CACHE_STATELESS:
1406  {
1407  size_t key_len;
1408  uint8_t *key_buff;
1409  EVP_PKEY_CTX *pkey_ctx = NULL;
1410 
1411  if (!(cache_conf->mode & FR_TLS_CACHE_STATEFUL)) tls_cache_disable_statefull_resumption(ctx);
1412 
1413  /*
1414  * If keys is NULL, then OpenSSL returns the expected
1415  * key length, which may be different across different
1416  * flavours/versions of OpenSSL.
1417  *
1418  * We could calculate this in conf.c, but, if in future
1419  * OpenSSL decides to use different key lengths based
1420  * on other parameters in the ctx, that'd break.
1421  */
1422  key_len = SSL_CTX_set_tlsext_ticket_keys(ctx, NULL, 0);
1423 
1424  if (unlikely((pkey_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL)) == NULL)) {
1425  fr_tls_strerror_printf(NULL);
1426  PERROR("Failed initialising KDF");
1427  kdf_error:
1428  if (pkey_ctx) EVP_PKEY_CTX_free(pkey_ctx);
1429  return -1;
1430  }
1431  if (unlikely(EVP_PKEY_derive_init(pkey_ctx) != 1)) {
1432  fr_tls_strerror_printf(NULL);
1433  PERROR("Failed initialising KDF derivation ctx");
1434  goto kdf_error;
1435  }
1436  if (unlikely(EVP_PKEY_CTX_set_hkdf_md(pkey_ctx, UNCONST(struct evp_md_st *, EVP_sha256())) != 1)) {
1437  fr_tls_strerror_printf(NULL);
1438  PERROR("Failed setting KDF MD");
1439  goto kdf_error;
1440  }
1441  if (unlikely(EVP_PKEY_CTX_set1_hkdf_key(pkey_ctx,
1442  UNCONST(unsigned char *, cache_conf->session_ticket_key),
1443  talloc_array_length(cache_conf->session_ticket_key)) != 1)) {
1444  fr_tls_strerror_printf(NULL);
1445  PERROR("Failed setting KDF key");
1446  goto kdf_error;
1447  }
1448  if (unlikely(EVP_PKEY_CTX_add1_hkdf_info(pkey_ctx,
1449  UNCONST(unsigned char *, "freeradius-session-ticket"),
1450  sizeof("freeradius-session-ticket") - 1) != 1)) {
1451  fr_tls_strerror_printf(NULL);
1452  PERROR("Failed setting KDF label");
1453  goto kdf_error;
1454  }
1455 
1456  /*
1457  * SSL_CTX_set_tlsext_ticket_keys memcpys its
1458  * inputs so this is just a temporary buffer.
1459  */
1460  MEM(key_buff = talloc_array(NULL, uint8_t, key_len));
1461  if (EVP_PKEY_derive(pkey_ctx, key_buff, &key_len) != 1) {
1462  fr_tls_strerror_printf(NULL);
1463  PERROR("Failed deriving session ticket key");
1464 
1465  talloc_free(key_buff);
1466  goto kdf_error;
1467  }
1468  EVP_PKEY_CTX_free(pkey_ctx);
1469 
1470  fr_assert(talloc_array_length(key_buff) == key_len);
1471  /*
1472  * Ensure the same keys are used across all threads
1473  */
1474  if (SSL_CTX_set_tlsext_ticket_keys(ctx,
1475  key_buff, key_len) != 1) {
1476  fr_tls_strerror_printf(NULL);
1477  PERROR("Failed setting session ticket keys");
1478  return -1;
1479  }
1480 
1481  DEBUG3("Derived session-ticket-key:");
1482  HEXDUMP3(key_buff, key_len, NULL);
1483  talloc_free(key_buff);
1484 
1485  /*
1486  * These callbacks embed and extract the
1487  * session-state list from the session-ticket.
1488  */
1489  if (unlikely(SSL_CTX_set_session_ticket_cb(ctx,
1490  tls_cache_session_ticket_app_data_set,
1491  tls_cache_session_ticket_app_data_get,
1492  UNCONST(fr_tls_cache_conf_t *, cache_conf)) != 1)) {
1493  fr_tls_strerror_printf(NULL);
1494  PERROR("Failed setting session ticket callbacks");
1495  return -1;
1496  }
1497 
1498  /*
1499  * Stateless resumption is enabled by default when
1500  * the TLS ctx is created, but OpenSSL sends too
1501  * many session tickets by default (2), and we only
1502  * need one.
1503  */
1504 #if OPENSSL_VERSION_NUMBER >= 0x10101000L
1505  SSL_CTX_set_num_tickets(ctx, 1);
1506 #endif
1507  }
1508  break;
1509  }
1510 
1511  SSL_CTX_set_not_resumable_session_callback(ctx, fr_tls_cache_disable_cb);
1512  SSL_CTX_set_quiet_shutdown(ctx, 1);
1513 
1514  return 0;
1515 }
1516 #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_FAIL
Encountered an unexpected error.
Definition: action.h:36
@ UNLANG_ACTION_CALCULATE_RESULT
Calculate a new section rlm_rcode_t value.
Definition: action.h:37
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition: build.h:165
#define USES_APPLE_DEPRECATED_API
Definition: build.h:431
#define RCSID(id)
Definition: build.h:444
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
Definition: build.h:320
#define unlikely(_x)
Definition: build.h:378
#define UNUSED
Definition: build.h:313
#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:762
static void fr_dbuff_free_talloc(fr_dbuff_t *dbuff)
Free the talloc buffer associated with a dbuff.
Definition: dbuff.h:448
#define fr_dbuff_len(_dbuff_or_marker)
The length of the underlying buffer.
Definition: dbuff.h:771
#define fr_dbuff_init(_out, _start, _len_or_end)
Initialise an dbuff for encoding or decoding.
Definition: dbuff.h:354
#define fr_dbuff_start(_dbuff_or_marker)
Return the 'start' position of a dbuff or marker.
Definition: dbuff.h:893
#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:738
static fr_dbuff_t * fr_dbuff_init_talloc(TALLOC_CTX *ctx, fr_dbuff_t *dbuff, fr_dbuff_uctx_talloc_t *tctx, size_t init, size_t max)
Initialise a special dbuff which automatically extends as additional data is written.
Definition: dbuff.h:406
static void * fr_dcursor_current(fr_dcursor_t *cursor)
Return the item the cursor current points to.
Definition: dcursor.h:336
#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:208
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition: dict_util.c:1997
bool unlang_request_is_cancelled(request_t const *request)
Return whether a request has been cancelled.
Definition: interpret.c:1310
void log_request_pair_list(fr_log_lvl_t lvl, request_t *request, fr_pair_t const *parent, fr_pair_list_t const *vps, char const *prefix)
Print a fr_pair_list_t.
Definition: log.c:821
#define PERROR(_fmt,...)
Definition: log.h:228
#define REXDENT()
Exdent (unindent) R* messages by one level.
Definition: log.h:443
#define DEBUG3(_fmt,...)
Definition: log.h:266
#define ROPTIONAL(_l_request, _l_global, _fmt,...)
Use different logging functions depending on whether request is NULL or not.
Definition: log.h:528
#define RWDEBUG(fmt,...)
Definition: log.h:361
#define RDEBUG_ENABLED3
True if request debug level 1-3 messages are enabled.
Definition: log.h:335
#define RDEBUG3(fmt,...)
Definition: log.h:343
#define RHEXDUMP4(_data, _len, _fmt,...)
Definition: log.h:706
#define ROPTIONAL_ENABLED(_e_request, _e_global)
Check if a debug level is set by the request (if !NULL) or by the global log.
Definition: log.h:542
#define RPERROR(fmt,...)
Definition: log.h:302
#define RPEDEBUG(fmt,...)
Definition: log.h:376
#define HEXDUMP3(_data, _len, _fmt,...)
Definition: log.h:723
#define RPWDEBUG(fmt,...)
Definition: log.h:366
#define DEBUG_ENABLED3
True if global debug level 1-3 messages are enabled.
Definition: log.h:259
#define RINDENT()
Indent R* messages by one level.
Definition: log.h:430
fr_value_box_t const * enum_tls_packet_type_store_session
HIDDEN fr_dict_attr_t const * attr_tls_packet_type
HIDDEN fr_dict_t const * dict_tls
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
HIDDEN fr_dict_attr_t const * attr_tls_session_id
fr_value_box_t const * enum_tls_packet_type_clear_session
fr_value_box_t const * enum_tls_packet_type_notfound
HIDDEN fr_dict_attr_t const * attr_allow_session_resumption
talloc_free(reap)
@ L_DBG_LVL_3
3rd highest priority debug messages (-xxx | -Xx).
Definition: log.h:72
@ L_DBG_LVL_2
2nd highest priority debug messages (-xx | -X).
Definition: log.h:71
@ L_DBG
Only displayed when debugging is enabled.
Definition: log.h:59
long int ssize_t
Definition: merged_model.c:24
unsigned char uint8_t
Definition: merged_model.c:30
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:688
int fr_pair_value_memdup_buffer(fr_pair_t *vp, uint8_t const *src, bool tainted)
Copy data from a talloced buffer into an "octets" data type.
Definition: pair.c:3008
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
Definition: pair.c:46
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.
Definition: pair.c:3053
ssize_t fr_internal_decode_pair_dbuff(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_attr_t const *parent, fr_dbuff_t *dbuff, void *decode_ctx)
Definition: decode.c:279
ssize_t fr_internal_encode_pair(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, void *encode_ctx)
Encode a data structure into an internal attribute.
Definition: encode.c:281
#define pair_update_request(_attr, _da)
Definition: radclient-ng.c:60
#define REDEBUG(fmt,...)
Definition: radclient.h:52
#define RDEBUG_ENABLED2()
Definition: radclient.h:50
#define RDEBUG2(fmt,...)
Definition: radclient.h:54
#define DEBUG2(fmt,...)
Definition: radclient.h:43
static rs_t * conf
Definition: radsniff.c:53
rlm_rcode_t
Return codes indicating the result of the module call.
Definition: rcode.h:40
#define pair_prepend_request(_attr, _da)
Allocate and prepend a fr_pair_t to the request list.
Definition: pair.h:77
fr_assert(0)
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
fr_pair_t * vp
#define fr_time()
Allow us to arbitrarily manipulate time.
Definition: state_test.c:8
Stores an attribute, a value and various bits of other data.
Definition: pair.h:68
request_t * unlang_subrequest_alloc(request_t *parent, fr_dict_t const *namespace)
Allocate a subrequest to run through a virtual server at some point in the future.
Definition: subrequest.c:266
uint8_t * talloc_typed_memdup(TALLOC_CTX *ctx, uint8_t const *in, size_t inlen)
Call talloc_memdup, setting the type on the new chunk correctly.
Definition: talloc.c:308
#define fr_time_lteq(_a, _b)
Definition: time.h:240
static int64_t fr_time_delta_to_sec(fr_time_delta_t delta)
Definition: time.h:645
static fr_time_t fr_time_from_sec(time_t when)
Convert a time_t (wallclock time) to a fr_time_t (internal time)
Definition: time.h:856
#define fr_time_sub(_a, _b)
Subtract one time from another.
Definition: time.h:229
"server local" time.
Definition: time.h:69
void fr_pair_list_free(fr_pair_list_t *list)
Free memory used by a valuepair list.
Definition: pair_inline.c:113
void fr_pair_list_append(fr_pair_list_t *dst, fr_pair_list_t *src)
Appends a list of fr_pair_t from a temporary list to a destination list.
Definition: pair_inline.c:182
#define fr_pair_dcursor_init(_cursor, _list)
Initialises a special dcursor with callbacks that will maintain the attr sublists correctly.
Definition: pair.h:590
void fr_value_box_memdup_shallow(fr_value_box_t *dst, fr_dict_attr_t const *enumv, uint8_t const *src, size_t len, bool tainted)
Assign a buffer to a box, but don't copy it.
Definition: value.c:4497
static fr_slen_t data
Definition: value.h:1259
#define fr_box_octets_buffer(_val)
Definition: value.h:283
int nonnull(2, 5))
static size_t char ** out
Definition: value.h:984
#define fr_box_octets(_val, _len)
Definition: value.h:281