From: Arran Cudbard-Bell Date: Thu, 24 Jun 2021 00:07:05 +0000 (-0500) Subject: Rework statefull session resumption so that the session-state list is part of the... X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5d757426412bda12182bfecec9c9ad855a025dc4;p=thirdparty%2Ffreeradius-server.git Rework statefull session resumption so that the session-state list is part of the application data Invert verb order for TLS packet-types so that it matches the sections Disable the old X509 stack based method of doing stateful revalidation, it wouldn't have worked if the peer included intermediaries, and it caused issues with newer versions of OpenSSL. --- diff --git a/raddb/mods-available/cache_tls b/raddb/mods-available/cache_tls index 2281c6d4edb..0b06db3e1ae 100644 --- a/raddb/mods-available/cache_tls +++ b/raddb/mods-available/cache_tls @@ -54,20 +54,7 @@ cache cache_tls_session { # update
{ ... }:: # update { - &session-state.Session-Data := &session-state.Session-Data - - # - # NOTE: If you want to store authorization attributes too, consider - # performing LDAP/SQL lookups in the tls-cache virtual server and - # storing the results in `&session-state`. - # - # The complete list can then be restored along with the - # `Session-Data` using the entry below. - # - # Policies run in `post-auth` then have access to the same data - # irrespective of whether the session is being resumed. - # -# &session-state += &session-state + &reply.Session-Data := &Session-Data } } diff --git a/share/dictionary/tls/dictionary.freeradius b/share/dictionary/tls/dictionary.freeradius index 79f85386851..aa8ec41adb9 100644 --- a/share/dictionary/tls/dictionary.freeradius +++ b/share/dictionary/tls/dictionary.freeradius @@ -10,10 +10,10 @@ ATTRIBUTE Packet-Type 1 uint32 -VALUE Packet-Type Session-Load 1 -VALUE Packet-Type Session-Store 2 -VALUE Packet-Type Session-Clear 3 -VALUE Packet-Type Certificate-Validate 4 +VALUE Packet-Type Load-Session 1 +VALUE Packet-Type Store-Session 2 +VALUE Packet-Type Clear-Session 3 +VALUE Packet-Type Verify-Certificate 4 # # We use response packet types instead of rcodes so that @@ -25,3 +25,5 @@ VALUE Packet-Type notfound 12 ATTRIBUTE Session-Id 10 octets ATTRIBUTE Session-Data 11 octets +ATTRIBUTE Session-Resumed 12 bool +ATTRIBUTE Session-TTL 13 time_delta diff --git a/src/lib/tls/attrs.h b/src/lib/tls/attrs.h index f54efe5b6d8..b7730400b6f 100644 --- a/src/lib/tls/attrs.h +++ b/src/lib/tls/attrs.h @@ -63,13 +63,15 @@ extern fr_dict_attr_t const *attr_tls_session_version; extern fr_dict_attr_t const *attr_tls_packet_type; extern fr_dict_attr_t const *attr_tls_session_data; extern fr_dict_attr_t const *attr_tls_session_id; +extern fr_dict_attr_t const *attr_tls_session_resumed; +extern fr_dict_attr_t const *attr_tls_session_ttl; extern fr_dict_attr_t const *attr_framed_mtu; -extern fr_value_box_t const *enum_tls_packet_type_session_load; -extern fr_value_box_t const *enum_tls_packet_type_session_store; -extern fr_value_box_t const *enum_tls_packet_type_session_clear; -extern fr_value_box_t const *enum_tls_packet_type_certificate_validate; +extern fr_value_box_t const *enum_tls_packet_type_load_session; +extern fr_value_box_t const *enum_tls_packet_type_store_session; +extern fr_value_box_t const *enum_tls_packet_type_clear_session; +extern fr_value_box_t const *enum_tls_packet_type_verify_certificate; extern fr_value_box_t const *enum_tls_packet_type_success; extern fr_value_box_t const *enum_tls_packet_type_failure; diff --git a/src/lib/tls/base.c b/src/lib/tls/base.c index 92103efff33..4efe8cbcc80 100644 --- a/src/lib/tls/base.c +++ b/src/lib/tls/base.c @@ -105,6 +105,8 @@ fr_dict_attr_t const *attr_framed_mtu; fr_dict_attr_t const *attr_tls_packet_type; fr_dict_attr_t const *attr_tls_session_data; fr_dict_attr_t const *attr_tls_session_id; +fr_dict_attr_t const *attr_tls_session_resumed; +fr_dict_attr_t const *attr_tls_session_ttl; extern fr_dict_attr_autoload_t tls_dict_attr[]; fr_dict_attr_autoload_t tls_dict_attr[] = { @@ -149,16 +151,18 @@ fr_dict_attr_autoload_t tls_dict_attr[] = { { .out = &attr_tls_packet_type, .name = "Packet-Type", .type = FR_TYPE_UINT32, .dict = &dict_tls }, { .out = &attr_tls_session_data, .name = "Session-Data", .type = FR_TYPE_OCTETS, .dict = &dict_tls }, { .out = &attr_tls_session_id, .name = "Session-Id", .type = FR_TYPE_OCTETS, .dict = &dict_tls }, + { .out = &attr_tls_session_resumed, .name = "Session-Resumed", .type = FR_TYPE_BOOL, .dict = &dict_tls }, + { .out = &attr_tls_session_ttl, .name = "Session-TTL", .type = FR_TYPE_TIME_DELTA, .dict = &dict_tls }, { NULL } }; /* * request types */ -fr_value_box_t const *enum_tls_packet_type_session_load; -fr_value_box_t const *enum_tls_packet_type_session_store; -fr_value_box_t const *enum_tls_packet_type_session_clear; -fr_value_box_t const *enum_tls_packet_type_certificate_validate; +fr_value_box_t const *enum_tls_packet_type_load_session; +fr_value_box_t const *enum_tls_packet_type_store_session; +fr_value_box_t const *enum_tls_packet_type_clear_session; +fr_value_box_t const *enum_tls_packet_type_verify_certificate; /* * response types @@ -169,10 +173,10 @@ fr_value_box_t const *enum_tls_packet_type_notfound; extern fr_dict_enum_autoload_t tls_dict_enum[]; fr_dict_enum_autoload_t tls_dict_enum[] = { - { .out = &enum_tls_packet_type_session_load, .name = "Session-Load", .attr = &attr_tls_packet_type }, - { .out = &enum_tls_packet_type_session_store, .name = "Session-Store", .attr = &attr_tls_packet_type }, - { .out = &enum_tls_packet_type_session_clear, .name = "Session-Clear", .attr = &attr_tls_packet_type }, - { .out = &enum_tls_packet_type_certificate_validate, .name = "Certificate-Validate", .attr = &attr_tls_packet_type }, + { .out = &enum_tls_packet_type_load_session, .name = "Load-Session", .attr = &attr_tls_packet_type }, + { .out = &enum_tls_packet_type_store_session, .name = "Store-Session", .attr = &attr_tls_packet_type }, + { .out = &enum_tls_packet_type_clear_session, .name = "Clear-Session", .attr = &attr_tls_packet_type }, + { .out = &enum_tls_packet_type_verify_certificate, .name = "Verify-Certificate", .attr = &attr_tls_packet_type }, { .out = &enum_tls_packet_type_success, .name = "Success", .attr = &attr_tls_packet_type }, { .out = &enum_tls_packet_type_failure, .name = "Failure", .attr = &attr_tls_packet_type }, diff --git a/src/lib/tls/cache.c b/src/lib/tls/cache.c index 522511b0bfe..61404f10ccb 100644 --- a/src/lib/tls/cache.c +++ b/src/lib/tls/cache.c @@ -29,6 +29,8 @@ USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */ #ifdef WITH_TLS #define LOG_PREFIX "tls - " +#include + #include #include #include @@ -105,6 +107,143 @@ void tls_cache_clear_state_reset(fr_tls_cache_t *cache) cache->clear.state = FR_TLS_CACHE_CLEAR_INIT; } +/** Serialize the session-state list and store it in the SSL_SESSION * + * + */ +static int tls_cache_app_data_set(request_t *request, SSL_SESSION *sess) +{ + fr_dbuff_t dbuff; + fr_dbuff_uctx_talloc_t tctx; + fr_dcursor_t dcursor; + fr_pair_t *vp; + ssize_t slen; + int ret; + + RDEBUG2("Adding &session-state[*] to session-ticket"); + RINDENT(); + log_request_pair_list(L_DBG_LVL_2, request, NULL, &request->session_state_pairs, NULL); + REXDENT(); + + /* + * Absolute maximum is `0..2^16-1`. + * + * We leave OpenSSL 2k to add anything else + */ + MEM(fr_dbuff_init_talloc(NULL, &dbuff, &tctx, 1024, 1024 * 62)); + + /* + * Encode the session-state contents and + * add it to the ticket. + */ + for (vp = fr_dcursor_init(&dcursor, &request->session_state_pairs); + vp; + vp = fr_dcursor_current(&dcursor)) { + slen = fr_internal_encode_pair(&dbuff, &dcursor, NULL); + if (slen < 0) { + RPERROR("Failed serialising session-state list"); + fr_dbuff_free_talloc(&dbuff); + return 0; + } + } + + RHEXDUMP4(fr_dbuff_start(&dbuff), fr_dbuff_used(&dbuff), "session-ticket application data"); + + /* + * Pass the serialized session-state list + * over to OpenSSL. + */ + ret = SSL_SESSION_set1_ticket_appdata(sess, fr_dbuff_start(&dbuff), fr_dbuff_used(&dbuff)); + fr_dbuff_free_talloc(&dbuff); /* OpenSSL memdups the data */ + if (ret != 1) { + fr_tls_log_error(request, "Failed setting application data for session-ticket"); + return -1; + } + + return 0; +} + +static int tls_cache_app_data_get(request_t *request, SSL_SESSION *sess) +{ + uint8_t *data; + size_t data_len; + fr_dbuff_t dbuff; + fr_pair_list_t tmp; + fr_dcursor_t cursor; + + /* + * Extract the session-state list from the ticket. + */ + if (SSL_SESSION_get0_ticket_appdata(sess, (void **)&data, &data_len) != 1) { + fr_tls_log_error(request, "Failed retrieving application data from session"); + return -1; + } + + fr_pair_list_init(&tmp); + fr_dcursor_init(&cursor, &tmp); + fr_dbuff_init(&dbuff, data, data_len); + + RHEXDUMP4(fr_dbuff_start(&dbuff), fr_dbuff_len(&dbuff), "session application data"); + + /* + * Decode the session-state data into a temporary list. + * + * It's very important that we decode _all_ attributes, + * or disallow session resumption. + */ + while (fr_dbuff_remaining(&dbuff) > 0) { + if (fr_internal_decode_pair_dbuff(request->session_state_ctx, &cursor, + request->dict, &dbuff, NULL) < 0) { + fr_pair_list_free(&tmp); + RPEDEBUG("Failed decoding session-state"); + return -1; + } + } + + RDEBUG2("Restoring &session-state[*] from session"); + RINDENT(); + log_request_pair_list(L_DBG_LVL_2, request, NULL, &tmp, "&session-state."); + REXDENT(); + + fr_pair_list_append(&request->session_state_pairs, &tmp); + + return 0; +} + +/** Delete session data be deleted from the cache + * + * @param[in] sess to be deleted. + */ +static void tls_cache_delete_request(SSL_SESSION *sess) +{ + fr_tls_session_t *tls_session; + fr_tls_cache_t *tls_cache; + request_t *request; + + tls_session = talloc_get_type_abort(SSL_SESSION_get_ex_data(sess, FR_TLS_EX_INDEX_TLS_SESSION), fr_tls_session_t); + + if (!tls_session->cache) return; + + request = fr_tls_session_request(tls_session->ssl); + tls_cache = tls_session->cache; + + fr_assert(tls_cache->clear.state == FR_TLS_CACHE_CLEAR_INIT); + + /* + * Record the session to delete + */ + tls_cache->clear.id = fr_tls_cache_id(tls_cache, sess); + if (!tls_cache->clear.id) { + RWDEBUG("Error retrieving Session ID"); + return; + } + + RDEBUG3("Requested session delete - ID %pV", fr_box_octets_buffer(tls_cache->clear.id)); + + tls_cache->clear.state = FR_TLS_CACHE_CLEAR_REQUESTED; + + ASYNC_pause_job(); /* Go do the delete _now_ */ +} + /** Process the result of `session load { ... }` */ static unlang_action_t tls_cache_load_result(UNUSED rlm_rcode_t *p_result, UNUSED int *priority, @@ -124,7 +263,7 @@ static unlang_action_t tls_cache_load_result(UNUSED rlm_rcode_t *p_result, UNUSE return UNLANG_ACTION_CALCULATE_RESULT; } - vp = fr_pair_find_by_da(&request->session_state_pairs, attr_tls_session_data, 0); + vp = fr_pair_find_by_da(&request->reply_pairs, attr_tls_session_data, 0); if (!vp) { RWDEBUG("No cached session found"); goto error; @@ -139,6 +278,7 @@ static unlang_action_t tls_cache_load_result(UNUSED rlm_rcode_t *p_result, UNUSE goto error; } RDEBUG3("Read %zu bytes of session data. Session deserialized successfully", vp->vp_length); + if (RDEBUG_ENABLED3) SSL_SESSION_print(fr_tls_request_log_bio(request, L_DBG, L_DBG_LVL_3), sess); /* * OpenSSL's API is very inconsistent. @@ -149,29 +289,11 @@ static unlang_action_t tls_cache_load_result(UNUSED rlm_rcode_t *p_result, UNUSE * ex_data is not serialised in i2d_SSL_SESSION * so we don't have to bother unsetting it. */ - SSL_SESSION_set_ex_data(sess, FR_TLS_EX_INDEX_TLS_SESSION, - SSL_get_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_TLS_SESSION)); + SSL_SESSION_set_ex_data(sess, FR_TLS_EX_INDEX_TLS_SESSION, fr_tls_session(tls_session->ssl)); tls_cache->load.state = FR_TLS_CACHE_LOAD_RETRIEVED; tls_cache->load.sess = sess; /* This is consumed in tls_cache_load_cb */ -#if 0 - /* - * We set the session here temporarily so that - * the certificate validation can run. - * - * FIXME - Do ASYNC session cert validation. - */ - SSL_set_session(ssl, sess); /* Increases ref count */ - - if (fr_tls_verify_client_cert_chain(ssl) != 1) { - RWDEBUG("Validation failed, forcefully expiring resumed session"); - SSL_SESSION_set_timeout(sess, 0); - } - - SSL_remove_session(ssl, sess); /* Decreases ref count */ -#endif - return UNLANG_ACTION_CALCULATE_RESULT; } @@ -190,6 +312,7 @@ static unlang_action_t tls_cache_load_push(request_t *request, fr_tls_session_t fr_tls_conf_t *conf = fr_tls_session_conf(tls_session->ssl); request_t *child; fr_pair_t *vp; + unlang_action_t ua; if (tls_cache->load.state != FR_TLS_CACHE_LOAD_REQUESTED) return UNLANG_ACTION_CALCULATE_RESULT; @@ -203,7 +326,7 @@ static unlang_action_t tls_cache_load_push(request_t *request, fr_tls_session_t * session resumption data. */ MEM(pair_prepend_request(&vp, attr_tls_packet_type) >= 0); - vp->vp_uint32 = enum_tls_packet_type_session_load->vb_uint32; + vp->vp_uint32 = enum_tls_packet_type_load_session->vb_uint32; /* * Add the session identifier we're @@ -215,13 +338,14 @@ static unlang_action_t tls_cache_load_push(request_t *request, fr_tls_session_t * Allocate a child, and set it up to call * the TLS virtual server. */ - if (fr_tls_call_push(child, tls_cache_load_result, conf, tls_session) < 0) { + ua = fr_tls_call_push(child, tls_cache_load_result, conf, tls_session); + if (ua < 0) { talloc_free(child); tls_cache_load_state_reset(tls_cache); return UNLANG_ACTION_FAIL; } - return UNLANG_ACTION_CALCULATE_RESULT; + return ua; } /** Process the result of `session store { ... }` @@ -267,10 +391,24 @@ unlang_action_t tls_cache_store_push(request_t *request, fr_tls_conf_t *conf, fr request_t *child; fr_pair_t *vp; SSL_SESSION *sess = tls_session->cache->store.sess; + unlang_action_t ua; + fr_time_t expires = fr_time_from_sec((time_t)(SSL_SESSION_get_time(sess) + SSL_get_timeout(sess))); + fr_time_t now = fr_time(); fr_assert(tls_cache->store.sess); fr_assert(tls_cache->store.state == FR_TLS_CACHE_STORE_REQUESTED); + if (expires <= now) { + RWDEBUG("Session has already expired, not storing"); + return UNLANG_ACTION_CALCULATE_RESULT; + } + + /* + * Add the current session-state list + * contents to the ssl-data + */ + if (tls_cache_app_data_set(request, sess) < 0) return UNLANG_ACTION_FAIL; + MEM(child = unlang_subrequest_alloc(request, dict_tls)); request = child; @@ -279,7 +417,7 @@ unlang_action_t tls_cache_store_push(request_t *request, fr_tls_conf_t *conf, fr * session resumption data. */ MEM(pair_prepend_request(&vp, attr_tls_packet_type) >= 0); - vp->vp_uint32 = enum_tls_packet_type_session_store->vb_uint32; + vp->vp_uint32 = enum_tls_packet_type_store_session->vb_uint32; /* * Add the session identifier we're trying @@ -288,6 +426,12 @@ unlang_action_t tls_cache_store_push(request_t *request, fr_tls_conf_t *conf, fr MEM(pair_update_request(&vp, attr_tls_session_id) >= 0); fr_pair_value_memdup_buffer_shallow(vp, fr_tls_cache_id(vp, sess), true); + /* + * How long the session has to live + */ + MEM(pair_update_request(&vp, attr_tls_session_ttl) >= 0); + vp->vp_time_delta = fr_time_delta_from_nsec(expires - now); + /* * Serialize the session */ @@ -304,6 +448,7 @@ unlang_action_t tls_cache_store_push(request_t *request, fr_tls_conf_t *conf, fr MEM(pair_update_request(&vp, attr_tls_session_data) >= 0); MEM(data = talloc_array(vp, uint8_t, len)); + /* openssl mutates &p */ p = data; ret = i2d_SSL_SESSION(sess, &p); /* Serialize as ASN.1 */ @@ -319,9 +464,10 @@ unlang_action_t tls_cache_store_push(request_t *request, fr_tls_conf_t *conf, fr * Allocate a child, and set it up to call * the TLS virtual server. */ - if (fr_tls_call_push(child, tls_cache_store_result, conf, tls_session) < 0) goto error; + ua = fr_tls_call_push(child, tls_cache_store_result, conf, tls_session); + if (ua < 0) goto error; - return UNLANG_ACTION_PUSHED_CHILD; + return ua; } /** Process the result of `session clear { ... }` @@ -362,6 +508,7 @@ unlang_action_t tls_cache_clear_push(request_t *request, fr_tls_conf_t *conf, fr request_t *child; fr_pair_t *vp; fr_tls_cache_t *tls_cache = tls_session->cache; + unlang_action_t ua; fr_assert(tls_cache->clear.state == FR_TLS_CACHE_CLEAR_REQUESTED); fr_assert(tls_cache->clear.id); @@ -369,21 +516,12 @@ unlang_action_t tls_cache_clear_push(request_t *request, fr_tls_conf_t *conf, fr MEM(child = unlang_subrequest_alloc(request, dict_tls)); request = child; - /* - * We never managed to store the session - * so don't bother trying to clear it. - */ - if (tls_cache->store.state != FR_TLS_CACHE_STORE_PERSISTED) { - tls_cache_clear_state_reset(tls_cache); - return UNLANG_ACTION_CALCULATE_RESULT; - } - /* * Setup the child request for loading * session resumption data. */ MEM(pair_prepend_request(&vp, attr_tls_packet_type) >= 0); - vp->vp_uint32 = enum_tls_packet_type_session_clear->vb_uint32; + vp->vp_uint32 = enum_tls_packet_type_clear_session->vb_uint32; /* * Add the session identifier we're @@ -395,13 +533,14 @@ unlang_action_t tls_cache_clear_push(request_t *request, fr_tls_conf_t *conf, fr * Allocate a child, and set it up to call * the TLS virtual server. */ - if (fr_tls_call_push(child, tls_cache_clear_result, conf, tls_session) < 0) { + ua = fr_tls_call_push(child, tls_cache_clear_result, conf, tls_session); + if (ua < 0) { talloc_free(child); tls_cache_clear_state_reset(tls_cache); return UNLANG_ACTION_FAIL; } - return UNLANG_ACTION_CALCULATE_RESULT; + return ua; } /** Push a `session store { ... }` or session clear { ... }` or `session load { ... }` depending on what operations are pending @@ -433,8 +572,18 @@ unlang_action_t fr_tls_cache_pending_push(request_t *request, fr_tls_session_t * if (tls_cache->clear.state == FR_TLS_CACHE_CLEAR_REQUESTED) { /* * Abort any pending store operations + * if they were for the same ID as + * we're now trying to clear. */ - if (tls_cache->store.state == FR_TLS_CACHE_STORE_REQUESTED) tls_cache_store_state_reset(tls_cache); + if (tls_cache->store.state == FR_TLS_CACHE_STORE_REQUESTED) { + unsigned int len; + uint8_t const *id; + + id = SSL_SESSION_get_id(tls_cache->store.sess, &len); + if ((len == talloc_array_length(tls_cache->clear.id)) && + (memcmp(tls_cache->clear.id, id, len) == 0)) tls_cache_store_state_reset(tls_cache); + } + return tls_cache_clear_push(request, conf, tls_session); } @@ -471,7 +620,7 @@ static int tls_cache_store_cb(SSL *ssl, SSL_SESSION *sess) * of the tls_session, as the fields aren't re-populated on * resumption. */ - tls_session = talloc_get_type_abort(SSL_get_ex_data(ssl, FR_TLS_EX_INDEX_TLS_SESSION), fr_tls_session_t); + tls_session = fr_tls_session(ssl); request = fr_tls_session_request(tls_session->ssl); tls_cache = tls_session->cache; @@ -506,9 +655,8 @@ static SSL_SESSION *tls_cache_load_cb(SSL *ssl, fr_tls_session_t *tls_session; fr_tls_cache_t *tls_cache; request_t *request; - SSL_SESSION *sess; - tls_session = talloc_get_type_abort(SSL_get_ex_data(ssl, FR_TLS_EX_INDEX_TLS_SESSION), fr_tls_session_t); + tls_session = fr_tls_session(ssl); request = fr_tls_session_request(tls_session->ssl); tls_cache = tls_session->cache; @@ -536,7 +684,7 @@ again: fr_assert(!tls_cache->load.id); tls_cache->load.state = FR_TLS_CACHE_LOAD_REQUESTED; - MEM(tls_cache->load.id = talloc_memdup(tls_cache, (uint8_t const *)key, key_len)); + MEM(tls_cache->load.id = talloc_typed_memdup(tls_cache, (uint8_t const *)key, key_len)); RDEBUG3("Requested session load - ID %pV", fr_box_octets_buffer(tls_cache->load.id)); ASYNC_pause_job(); @@ -548,15 +696,57 @@ again: break; case FR_TLS_CACHE_LOAD_RETRIEVED: + { TALLOC_FREE(tls_cache->load.id); RDEBUG3("Setting session data"); + /* + * This restores the contents of &session-state[*] + * which hopefully still contains all the certificate + * pairs. + * + * Although the SSL_SESSION does contain a copy of + * the peer's certificate, it does not contain the + * peer's certificate chain, and so isn't reliable + * for performing re-validation. + */ + if (tls_cache_app_data_get(request, tls_cache->load.sess) < 0) { + REDEBUG("Denying session resumption via session-id"); + verify_error: + /* + * Request the session be deleted the next + * time something calls cache action pending. + */ + tls_cache_delete_request(tls_cache->load.sess); + tls_cache_load_state_reset(tls_session->cache); /* Free the session */ + return NULL; + } + + /* + * This sets the validation state of the tls_session + * so that when we call ASYNC_pause_job(), and execution + * jumps back to tls_session_async_handshake_cont + * (just under SSL_read()) + * the code there knows what job it needs to push onto + * the unlang stack. + */ + fr_tls_verify_client_cert_request(tls_session, true); + + ASYNC_pause_job(); + + /* + * If we couldn't validate the client certificate + * then validation overall fails. + */ + if (!fr_tls_verify_client_cert_result(tls_session)) { + RDEBUG2("Certificate re-validation failed, denying session resumption via session-id"); + goto verify_error; + } + *copy = 0; - tls_cache->load.state = FR_TLS_CACHE_LOAD_INIT; /* Reset state */ - sess = tls_cache->load.sess; - tls_cache->load.sess = NULL; - return sess; + } + return tls_cache->load.sess; case FR_TLS_CACHE_LOAD_FAILED: RDEBUG3("Session data load failed"); @@ -576,31 +766,14 @@ again: */ static void tls_cache_delete_cb(UNUSED SSL_CTX *ctx, SSL_SESSION *sess) { - fr_tls_session_t *tls_session; - fr_tls_cache_t *tls_cache; - request_t *request; - - tls_session = talloc_get_type_abort(SSL_SESSION_get_ex_data(sess, FR_TLS_EX_INDEX_TLS_SESSION), fr_tls_session_t); - - if (!tls_session->cache) return; - - request = fr_tls_session_request(tls_session->ssl); - tls_cache = tls_session->cache; - - fr_assert(tls_cache->clear.state == FR_TLS_CACHE_CLEAR_INIT); - - RDEBUG3("Requested session delete - ID %pV", fr_box_octets_buffer(tls_cache->clear.id)); - /* - * Record the session to delete + * Not sure why this happens, but sometimes SSL_SESSION *s + * make it here without the correct ex data. + * + * Maybe it's one OpenSSL created internally? */ - tls_cache->clear.id = fr_tls_cache_id(tls_cache, sess); - if (!tls_cache->clear.id) { - RWDEBUG("Error retrieving Session ID"); - return; - } - - tls_cache->clear.state = FR_TLS_CACHE_CLEAR_REQUESTED; + if (!SSL_SESSION_get_ex_data(sess, FR_TLS_EX_INDEX_TLS_SESSION)) return; + tls_cache_delete_request(sess); } /** Prevent a TLS session from being resumed in future @@ -621,14 +794,14 @@ int fr_tls_cache_disable_cb(SSL *ssl, int is_forward_secure) fr_tls_session_t *tls_session; fr_pair_t *vp; - tls_session = talloc_get_type_abort(SSL_get_ex_data(ssl, FR_TLS_EX_INDEX_TLS_SESSION), fr_tls_session_t); + tls_session = fr_tls_session(ssl); request = fr_tls_session_request(tls_session->ssl); { fr_tls_conf_t *conf; conf = talloc_get_type_abort(SSL_get_ex_data(ssl, FR_TLS_EX_INDEX_CONF), fr_tls_conf_t); - if (conf->cache.require_extms && (SSL_get_extms_support(tls_session->ssl) != 1)) { + if (conf->cache.require_extms && (SSL_get_extms_support(tls_session->ssl) == 0)) { RDEBUG2("Client does not support the Extended Master Secret extension, " "denying session resumption"); goto disable; @@ -774,12 +947,6 @@ static int tls_cache_session_ticket_app_data_set(SSL *ssl, void *arg) fr_tls_cache_conf_t *tls_cache_conf = arg; /* Not talloced */ SSL_SESSION *sess; request_t *request; - ssize_t slen; - fr_dbuff_t dbuff; - fr_dbuff_uctx_talloc_t tctx; - fr_dcursor_t dcursor; - fr_pair_t *vp; - int ret; /* * Check to see if we have a request bound @@ -814,45 +981,7 @@ static int tls_cache_session_ticket_app_data_set(SSL *ssl, void *arg) return 0; } - RDEBUG2("Adding &session-state[*] to session-ticket"); - RINDENT(); - log_request_pair_list(L_DBG_LVL_2, request, NULL, &request->session_state_pairs, NULL); - REXDENT(); - - /* - * Absolute maximum is `0..2^16-1`. - * - * We leave OpenSSL 2k to add anything else - */ - MEM(fr_dbuff_init_talloc(NULL, &dbuff, &tctx, 1024, 1024 * 62)); - - /* - * Encode the session-state contents and - * add it to the ticket. - */ - for (vp = fr_dcursor_init(&dcursor, &request->session_state_pairs); - vp; - vp = fr_dcursor_current(&dcursor)) { - slen = fr_internal_encode_pair(&dbuff, &dcursor, NULL); - if (slen < 0) { - RPERROR("Failed serialising session-state list"); - fr_dbuff_free_talloc(&dbuff); - return 0; - } - } - - RHEXDUMP4(fr_dbuff_start(&dbuff), fr_dbuff_used(&dbuff), "session-ticket application data"); - - /* - * Pass the serialized session-state list - * over to OpenSSL. - */ - ret = SSL_SESSION_set1_ticket_appdata(sess, fr_dbuff_start(&dbuff), fr_dbuff_used(&dbuff)); - fr_dbuff_free_talloc(&dbuff); /* OpenSSL memdups the data */ - if (ret != 1) { - fr_tls_log_error(request, "Failed setting application data for session-ticket"); - return 0; - } + if (tls_cache_app_data_set(request, sess) < 0) return 0; return 1; } @@ -871,11 +1000,6 @@ static SSL_TICKET_RETURN tls_cache_session_ticket_app_data_get(SSL *ssl, SSL_SES fr_tls_conf_t *conf = fr_tls_session_conf(tls_session->ssl); fr_tls_cache_conf_t *tls_cache_conf = arg; /* Not talloced */ request_t *request = NULL; - uint8_t *data; - size_t data_len; - fr_dbuff_t dbuff; - fr_pair_list_t tmp; - fr_dcursor_t cursor; if (fr_tls_session_request_bound(ssl)) request = fr_tls_session_request(ssl); @@ -904,53 +1028,31 @@ static SSL_TICKET_RETURN tls_cache_session_ticket_app_data_get(SSL *ssl, SSL_SES } /* - * Extract the session-state list from the ticket. - */ - if (SSL_SESSION_get0_ticket_appdata(sess, (void **)&data, &data_len) != 1) { - fr_tls_log_error(request, "Failed retrieving application data from session-ticket, " - "denying session resumption via session-ticket"); - return SSL_TICKET_RETURN_IGNORE_RENEW; - } - - fr_pair_list_init(&tmp); - fr_dcursor_init(&cursor, &tmp); - fr_dbuff_init(&dbuff, data, data_len); - - RHEXDUMP4(fr_dbuff_start(&dbuff), fr_dbuff_len(&dbuff), "session-ticket application data"); - - /* - * Decode the session-state data into a temporary list. + * This restores the contents of &session-state[*] + * which hopefully still contains all the certificate + * pairs. * - * It's very important that we decode _all_ attributes, - * or disallow session resumption. + * Although the SSL_SESSION does contain a copy of + * the peer's certificate, it does not contain the + * peer's certificate chain, and so isn't reliable + * for performing re-validation. */ - while (fr_dbuff_remaining(&dbuff) > 0) { - if (fr_internal_decode_pair_dbuff(request->session_state_ctx, &cursor, - request->dict, &dbuff, NULL) < 0) { - fr_pair_list_free(&tmp); - RPEDEBUG("Failed decoding session-state, denying session resumption via session-ticket"); - return SSL_TICKET_RETURN_IGNORE_RENEW; - } + if (tls_cache_app_data_get(request, sess) < 0) { + REDEBUG("Denying session resumption via session-ticket"); + return SSL_TICKET_RETURN_IGNORE_RENEW; } - RDEBUG2("Restoring &session-state[*] from session-ticket"); - RINDENT(); - log_request_pair_list(L_DBG_LVL_2, request, NULL, &tmp, "&session-state."); - REXDENT(); - - fr_pair_list_append(&request->session_state_pairs, &tmp); - if (conf->virtual_server && tls_session->verify_client_cert) { RDEBUG2("Requesting certificate re-validation for session-ticket"); /* * This sets the validation state of the tls_session * so that when we call ASYNC_pause_job(), and execution * jumps back to tls_session_async_handshake_cont - * (just under SSL_read()) + * (just under SSL_read()) * the code there knows what job it needs to push onto * the unlang stack. */ - fr_tls_verify_client_cert_request(tls_session); + fr_tls_verify_client_cert_request(tls_session, true); ASYNC_pause_job(); @@ -959,7 +1061,7 @@ static SSL_TICKET_RETURN tls_cache_session_ticket_app_data_get(SSL *ssl, SSL_SES * give the client the opportunity to send a new * one, but _don't_ allow session resumption. */ - if (!fr_tls_verify_client_cert_successful(tls_session)) { + if (!fr_tls_verify_client_cert_result(tls_session)) { RDEBUG2("Certificate re-validation failed, denying session resumption via session-ticket"); return SSL_TICKET_RETURN_IGNORE_RENEW; } diff --git a/src/lib/tls/conf.c b/src/lib/tls/conf.c index 3a1fd29e309..b1b79400441 100644 --- a/src/lib/tls/conf.c +++ b/src/lib/tls/conf.c @@ -90,7 +90,7 @@ static CONF_PARSER tls_cache_config[] = { { FR_CONF_OFFSET("lifetime", FR_TYPE_UINT32, fr_tls_cache_conf_t, lifetime), .dflt = "86400" }, #if OPENSSL_VERSION_NUMBER >= 0x10100000L - { FR_CONF_OFFSET("require_extended_master_secret", FR_TYPE_BOOL, fr_tls_cache_conf_t, require_extms), .dflt = "no" }, + { FR_CONF_OFFSET("require_extended_master_secret", FR_TYPE_BOOL, fr_tls_cache_conf_t, require_extms), .dflt = "yes" }, { FR_CONF_OFFSET("require_perfect_forward_secrecy", FR_TYPE_BOOL, fr_tls_cache_conf_t, require_pfs), .dflt = "no" }, #endif @@ -190,7 +190,7 @@ CONF_PARSER fr_tls_server_config[] = { { FR_CONF_OFFSET("tls_min_version", FR_TYPE_FLOAT32, fr_tls_conf_t, tls_min_version), .dflt = "1.2" }, - { FR_CONF_OFFSET("cache", FR_TYPE_SUBSECTION, fr_tls_conf_t, cache), .subcs = (void const *) tls_cache_config }, + { FR_CONF_OFFSET("session", FR_TYPE_SUBSECTION, fr_tls_conf_t, cache), .subcs = (void const *) tls_cache_config }, { FR_CONF_OFFSET("verify", FR_TYPE_SUBSECTION, fr_tls_conf_t, verify), .subcs = (void const *) tls_verify_config }, @@ -404,20 +404,20 @@ fr_tls_conf_t *fr_tls_conf_parse_server(CONF_SECTION *cs) goto error; } - if (!cf_section_find(conf->virtual_server, "load", "cache")) { - ERROR("Specified virtual_server must contain a \"load cache { ... }\" section " + if (!cf_section_find(conf->virtual_server, "load", "session")) { + ERROR("Specified virtual_server must contain a \"load session { ... }\" section " "when cache.mode = \"stateful\""); goto error; } - if (!cf_section_find(conf->virtual_server, "store", "cache")) { - ERROR("Specified virtual_server must contain a \"store cache { ... }\" section " + if (!cf_section_find(conf->virtual_server, "store", "session")) { + ERROR("Specified virtual_server must contain a \"store session { ... }\" section " "when cache.mode = \"stateful\""); goto error; } - if (!cf_section_find(conf->virtual_server, "clear", "cache")) { - ERROR("Specified virtual_server must contain a \"clear cache { ... }\" section " + if (!cf_section_find(conf->virtual_server, "clear", "session")) { + ERROR("Specified virtual_server must contain a \"clear session { ... }\" section " "when cache.mode = \"stateful\""); goto error; } @@ -437,19 +437,19 @@ fr_tls_conf_t *fr_tls_conf_parse_server(CONF_SECTION *cs) break; } - if (!cf_section_find(conf->virtual_server, "load", "cache")) { - WARN("Specified virtual_server missing \"load cache { ... }\" section. " + if (!cf_section_find(conf->virtual_server, "load", "session")) { + WARN("Specified virtual_server missing \"load session { ... }\" section. " "cache.mode = \"auto\" rewritten to cache.mode = \"stateless\""); goto cache_stateless; } - if (!cf_section_find(conf->virtual_server, "store", "cache")) { - WARN("Specified virtual_server missing \"store cache { ... }\" section. " + if (!cf_section_find(conf->virtual_server, "store", "session")) { + WARN("Specified virtual_server missing \"store session { ... }\" section. " "cache.mode = \"auto\" rewritten to cache.mode = \"stateless\""); goto cache_stateless; } - if (!cf_section_find(conf->virtual_server, "clear", "cache")) { + if (!cf_section_find(conf->virtual_server, "clear", "session")) { WARN("Specified virtual_server missing \"clear cache { ... }\" section. " "cache.mode = \"auto\" rewritten to cache.mode = \"stateless\""); goto cache_stateless; diff --git a/src/lib/tls/session.c b/src/lib/tls/session.c index 6653ca5032e..d0a59491619 100644 --- a/src/lib/tls/session.c +++ b/src/lib/tls/session.c @@ -1034,6 +1034,9 @@ static unlang_action_t tls_session_async_handshake_done_round(UNUSED rlm_rcode_t { fr_tls_session_t *tls_session = talloc_get_type_abort(uctx, fr_tls_session_t); int ret; + + RDEBUG3("entered state %s", __FUNCTION__); + /* * This only occurs once per session, where calling * SSL_read updates the state of the SSL session, setting @@ -1191,6 +1194,8 @@ static unlang_action_t tls_session_async_handshake_cont(rlm_rcode_t *p_result, i fr_tls_session_t *tls_session = talloc_get_type_abort(uctx, fr_tls_session_t); int ret; + RDEBUG3("(re-)entered state %s", __FUNCTION__); + /* * Magic/More magic? Although SSL_read is normally * used to read application data, it will also @@ -1237,6 +1242,9 @@ static unlang_action_t tls_session_async_handshake_cont(rlm_rcode_t *p_result, i case SSL_ERROR_WANT_ASYNC: /* Certification validation or cache loads */ { unlang_action_t ua; + + RDEBUG3("Performing async action for OpenSSL"); + /* * Call this function again once we're done * asynchronously satisfying the load request. @@ -1311,6 +1319,8 @@ static unlang_action_t tls_session_async_handshake(rlm_rcode_t *p_result, int *p fr_tls_session_t *tls_session = talloc_get_type_abort(uctx, fr_tls_session_t); int ret; + RDEBUG3("entered state %s", __FUNCTION__); + tls_session->result = FR_TLS_RESULT_IN_PROGRESS; fr_tls_session_request_bind(tls_session->ssl, request); diff --git a/src/lib/tls/verify.c b/src/lib/tls/verify.c index d305d9cb737..ef84b576f7c 100644 --- a/src/lib/tls/verify.c +++ b/src/lib/tls/verify.c @@ -199,11 +199,39 @@ int fr_tls_verify_cert_cb(int ok, X509_STORE_CTX *x509_ctx) } done: /* - * This is a client cert + * This is a client cert, call our + * virtual server here. */ - if (depth == 0) tls_session->client_cert_ok = (my_ok > 0); + if (depth == 0) { + if (conf->virtual_server && tls_session->verify_client_cert) { + RDEBUG2("Requesting certificate validation"); - RDEBUG2("[verify] = %s", my_ok ? "ok" : "invalid"); + /* + * This sets the validation state of the tls_session + * so that when we call ASYNC_pause_job(), and execution + * jumps back to tls_session_async_handshake_cont + * (just under SSL_read()) + * the code there knows what job it needs to push onto + * the unlang stack. + */ + fr_tls_verify_client_cert_request(tls_session, SSL_session_reused(tls_session->ssl)); + + ASYNC_pause_job(); + + /* + * If we couldn't validate the client certificate + * then validation overall fails. + */ + if (!fr_tls_verify_client_cert_result(tls_session)) { + REDEBUG("Certificate validation failed"); + my_ok = 0; + X509_STORE_CTX_set_error(x509_ctx, X509_V_ERR_APPLICATION_VERIFICATION); + } + } + + tls_session->client_cert_ok = (my_ok > 0); + RDEBUG2("[verify] = %s", my_ok ? "ok" : "invalid"); + } return my_ok; } @@ -222,7 +250,7 @@ DIAG_ON(DIAG_UNKNOWN_PRAGMAS) * - 1 if the chain could be validated. * - 0 if the chain failed validation. */ -int fr_tls_verify_client_cert_chain(SSL *ssl) +int fr_tls_verify_client_cert_chain(request_t *request, SSL *ssl) { int err; int verify; @@ -233,8 +261,6 @@ int fr_tls_verify_client_cert_chain(SSL *ssl) X509_STORE *store; X509_STORE_CTX *store_ctx; - request_t *request = fr_tls_session_request(ssl); - /* * If there's no client certificate, we just return OK. */ @@ -319,7 +345,10 @@ static unlang_action_t tls_verify_client_cert_push(request_t *request, fr_tls_se * session resumption data. */ MEM(pair_prepend_request(&vp, attr_tls_packet_type) >= 0); - vp->vp_uint32 = enum_tls_packet_type_certificate_validate->vb_uint32; + vp->vp_uint32 = enum_tls_packet_type_verify_certificate->vb_uint32; + + MEM(pair_append_request(&vp, attr_tls_session_resumed) >= 0); + vp->vp_bool = tls_session->validate.resumed; /* * Allocate a child, and set it up to call @@ -335,22 +364,38 @@ static unlang_action_t tls_verify_client_cert_push(request_t *request, fr_tls_se return ua; } -/** Check we validated the client cert successfully +/** Clear any previous validation result * + * Should be called by the validation requestor to get the result and reset + * the validation state. + * + * @return + * - true if the certificate chain was validated. + * - false if the certificate chain failed validation. */ -bool fr_tls_verify_client_cert_successful(fr_tls_session_t *tls_session) +bool fr_tls_verify_client_cert_result(fr_tls_session_t *tls_session) { - return tls_session->validate.state == FR_TLS_VALIDATION_SUCCESS; + bool result; + + fr_assert(tls_session->validate.state != FR_TLS_VALIDATION_INIT); + + result = tls_session->validate.state == FR_TLS_VALIDATION_SUCCESS; + + tls_session->validate.state = FR_TLS_VALIDATION_INIT; + tls_session->validate.resumed = false; + + return result; } /** Setup a validation request * */ -void fr_tls_verify_client_cert_request(fr_tls_session_t *tls_session) +void fr_tls_verify_client_cert_request(fr_tls_session_t *tls_session, bool session_resumed) { fr_assert(tls_session->validate.state == FR_TLS_VALIDATION_INIT); tls_session->validate.state = FR_TLS_VALIDATION_REQUESTED; + tls_session->validate.resumed = session_resumed; } /** Push a `verify certificate { ... }` section diff --git a/src/lib/tls/verify.h b/src/lib/tls/verify.h index e18cf28a28f..309099473cf 100644 --- a/src/lib/tls/verify.h +++ b/src/lib/tls/verify.h @@ -61,11 +61,7 @@ typedef struct { fr_tls_validation_state_t state; //!< Whether OpenSSL has requested ///< certificate validation. - bool first_call; //!< Is this the first call into the validation - ///< routine. - bool have_pairs; //!< When we entered the validation call we found - ///< pre-existing pairs in the session-state list - ///< so we will not regenerate the c + bool resumed; //!< Whether we're validating a resumed session. } fr_tls_verify_t; #ifdef __cplusplus @@ -80,11 +76,11 @@ extern "C" { int fr_tls_verify_cert_cb(int ok, X509_STORE_CTX *ctx); -int fr_tls_verify_client_cert_chain(SSL *ssl); +int fr_tls_verify_client_cert_chain(request_t *request, SSL *ssl); -bool fr_tls_verify_client_cert_successful(fr_tls_session_t *tls_session); +bool fr_tls_verify_client_cert_result(fr_tls_session_t *tls_session); -void fr_tls_verify_client_cert_request(fr_tls_session_t *tls_session); +void fr_tls_verify_client_cert_request(fr_tls_session_t *tls_session, bool resumed); unlang_action_t fr_tls_verify_client_cert_pending_push(request_t *request, fr_tls_session_t *tls_session); diff --git a/src/lib/util/pair.h b/src/lib/util/pair.h index ec859e2dfcb..be80e24a6b8 100644 --- a/src/lib/util/pair.h +++ b/src/lib/util/pair.h @@ -137,6 +137,7 @@ typedef struct { #define vp_float64 data.vb_float64 #define vp_date data.vb_date +#define vp_time_delta data.vb_time_delta #define vp_group children diff --git a/src/modules/rlm_eap/types/rlm_eap_fast/rlm_eap_fast.c b/src/modules/rlm_eap/types/rlm_eap_fast/rlm_eap_fast.c index a65b3a01dca..7ee73822ad9 100644 --- a/src/modules/rlm_eap/types/rlm_eap_fast/rlm_eap_fast.c +++ b/src/modules/rlm_eap/types/rlm_eap_fast/rlm_eap_fast.c @@ -463,6 +463,12 @@ static unlang_action_t mod_handshake_resume(rlm_rcode_t *p_result, UNUSED module * @todo - generate MPPE keys, which have their own magical deriviation. */ + /* + * Result is always OK, even if we fail to persist the + * session data. + */ + *p_result = RLM_MODULE_OK; + /* * Write the session to the session cache * diff --git a/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c b/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c index 2075ea21197..d1d2d2312dc 100644 --- a/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c +++ b/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c @@ -72,6 +72,12 @@ fr_dict_attr_autoload_t rlm_eap_tls_dict_attr[] = { { NULL } }; +static unlang_action_t mod_handshake_done(rlm_rcode_t *p_result, UNUSED module_ctx_t const *mctx, + UNUSED request_t *request, UNUSED void *rctx) +{ + RETURN_MODULE_OK; +} + static unlang_action_t mod_handshake_resume(rlm_rcode_t *p_result, UNUSED module_ctx_t const *mctx, request_t *request, void *rctx) { @@ -103,6 +109,11 @@ static unlang_action_t mod_handshake_resume(rlm_rcode_t *p_result, UNUSED module if (eap_tls_success(request, eap_session, &prf_label) < 0) RETURN_MODULE_FAIL; + /* + * Result is always OK, even if we fail to persist the + * session data. + */ + unlang_module_yield(request, mod_handshake_done, NULL, NULL); /* * Write the session to the session cache * diff --git a/src/modules/rlm_eap/types/rlm_eap_ttls/rlm_eap_ttls.c b/src/modules/rlm_eap/types/rlm_eap_ttls/rlm_eap_ttls.c index ca8ff8ec83d..e68ab039139 100644 --- a/src/modules/rlm_eap/types/rlm_eap_ttls/rlm_eap_ttls.c +++ b/src/modules/rlm_eap/types/rlm_eap_ttls/rlm_eap_ttls.c @@ -170,6 +170,11 @@ static unlang_action_t mod_handshake_resume(rlm_rcode_t *p_result, UNUSED module * Success: Automatically return MPPE keys. */ if (eap_tls_success(request, eap_session, &prf_label) < 0) RETURN_MODULE_FAIL; + + /* + * Result is always OK, even if we fail to persist the + * session data. + */ *p_result = RLM_MODULE_OK; /* diff --git a/src/process/tls/base.c b/src/process/tls/base.c index bdcc23bf24a..abf440e7bcd 100644 --- a/src/process/tls/base.c +++ b/src/process/tls/base.c @@ -43,10 +43,10 @@ fr_dict_attr_autoload_t process_tls_dict_attr[] = { }; typedef struct { - CONF_SECTION *session_load; - CONF_SECTION *session_store; - CONF_SECTION *session_clear; - CONF_SECTION *certificate_validate; + CONF_SECTION *load_session; + CONF_SECTION *store_session; + CONF_SECTION *clear_session; + CONF_SECTION *verify_certificate; } process_tls_sections_t; typedef struct { @@ -62,7 +62,7 @@ typedef struct { #include static fr_process_state_t const process_state[] = { - [FR_PACKET_TYPE_VALUE_SESSION_LOAD] = { + [FR_PACKET_TYPE_VALUE_LOAD_SESSION] = { .packet_type = { [RLM_MODULE_OK] = FR_PACKET_TYPE_VALUE_SUCCESS, [RLM_MODULE_UPDATED] = FR_PACKET_TYPE_VALUE_SUCCESS, @@ -77,9 +77,9 @@ static fr_process_state_t const process_state[] = { .rcode = RLM_MODULE_NOOP, .recv = recv_generic, .resume = resume_recv_no_send, - .section_offset = PROCESS_CONF_OFFSET(session_load), + .section_offset = PROCESS_CONF_OFFSET(load_session), }, - [FR_PACKET_TYPE_VALUE_SESSION_STORE] = { + [FR_PACKET_TYPE_VALUE_STORE_SESSION] = { .packet_type = { [RLM_MODULE_OK] = FR_PACKET_TYPE_VALUE_SUCCESS, [RLM_MODULE_UPDATED] = FR_PACKET_TYPE_VALUE_SUCCESS, @@ -94,9 +94,9 @@ static fr_process_state_t const process_state[] = { .rcode = RLM_MODULE_NOOP, .recv = recv_generic, .resume = resume_recv_no_send, - .section_offset = PROCESS_CONF_OFFSET(session_store), + .section_offset = PROCESS_CONF_OFFSET(store_session), }, - [FR_PACKET_TYPE_VALUE_SESSION_CLEAR] = { + [FR_PACKET_TYPE_VALUE_CLEAR_SESSION] = { .packet_type = { [RLM_MODULE_OK] = FR_PACKET_TYPE_VALUE_SUCCESS, [RLM_MODULE_UPDATED] = FR_PACKET_TYPE_VALUE_SUCCESS, @@ -111,14 +111,14 @@ static fr_process_state_t const process_state[] = { .rcode = RLM_MODULE_NOOP, .recv = recv_generic, .resume = resume_recv_no_send, - .section_offset = PROCESS_CONF_OFFSET(session_clear), + .section_offset = PROCESS_CONF_OFFSET(clear_session), }, - [FR_PACKET_TYPE_VALUE_CERTIFICATE_VALIDATE] = { + [FR_PACKET_TYPE_VALUE_VERIFY_CERTIFICATE] = { .packet_type = { [RLM_MODULE_OK] = FR_PACKET_TYPE_VALUE_SUCCESS, + [RLM_MODULE_UPDATED] = FR_PACKET_TYPE_VALUE_SUCCESS, + [RLM_MODULE_NOOP] = FR_PACKET_TYPE_VALUE_SUCCESS, - [RLM_MODULE_UPDATED] = FR_PACKET_TYPE_VALUE_FAILURE, - [RLM_MODULE_NOOP] = FR_PACKET_TYPE_VALUE_FAILURE, [RLM_MODULE_REJECT] = FR_PACKET_TYPE_VALUE_FAILURE, [RLM_MODULE_FAIL] = FR_PACKET_TYPE_VALUE_FAILURE, [RLM_MODULE_INVALID] = FR_PACKET_TYPE_VALUE_FAILURE, @@ -128,7 +128,7 @@ static fr_process_state_t const process_state[] = { .rcode = RLM_MODULE_NOOP, .recv = recv_generic, .resume = resume_recv_no_send, - .section_offset = PROCESS_CONF_OFFSET(certificate_validate), + .section_offset = PROCESS_CONF_OFFSET(verify_certificate), }, }; @@ -156,25 +156,25 @@ static const virtual_server_compile_t compile_list[] = { .name = "store", .name2 = "session", .component = MOD_AUTHORIZE, - .offset = PROCESS_CONF_OFFSET(session_store) + .offset = PROCESS_CONF_OFFSET(store_session) }, { .name = "load", .name2 = "session", .component = MOD_AUTHORIZE, - .offset = PROCESS_CONF_OFFSET(session_load) + .offset = PROCESS_CONF_OFFSET(load_session) }, { .name = "clear", .name2 = "session", .component = MOD_AUTHORIZE, - .offset = PROCESS_CONF_OFFSET(session_clear) + .offset = PROCESS_CONF_OFFSET(clear_session) }, { .name = "verify", .name2 = "certificate", .component = MOD_AUTHORIZE, - .offset = PROCESS_CONF_OFFSET(certificate_validate) + .offset = PROCESS_CONF_OFFSET(verify_certificate) }, COMPILE_TERMINATOR }; diff --git a/src/tests/eapol_test/config/tls/mods-enabled/cache b/src/tests/eapol_test/config/tls/mods-enabled/cache new file mode 100644 index 00000000000..fb20ae4a296 --- /dev/null +++ b/src/tests/eapol_test/config/tls/mods-enabled/cache @@ -0,0 +1,23 @@ +cache cache_tls_session { + # + # driver:: `cache` driver. + # + driver = "rlm_cache_rbtree" + + # + # key:: The `cache` key. + # + key = &Session-Id + + # + # ttl:: TTL for `cache` entries. + # + ttl = 3600 + + # + # update
{ ... }:: + # + update { + &reply.Session-Data := &Session-Data + } +} diff --git a/src/tests/eapol_test/config/tls/sites-enabled/tls b/src/tests/eapol_test/config/tls/sites-enabled/tls index 8e0d616935c..c12636a21d6 100644 --- a/src/tests/eapol_test/config/tls/sites-enabled/tls +++ b/src/tests/eapol_test/config/tls/sites-enabled/tls @@ -1,7 +1,29 @@ server eap-tls-test { namespace = tls + load session { + update control { + &control.Cache-Allow-Insert := no + } + cache_tls_session + } + + store session { + cache_tls_session + } + + clear session { + update control { + &control.Cache-Allow-Insert := no + &control.Cache-Allow-Merge := no + &control.Cache-TTL := 0 + } + cache_tls_session + } + verify certificate { - ok + if (&Session-Resumed == true) { + reject + } } }