]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Add an optional "establish session" session
authorNick Porter <nick@portercomputing.co.uk>
Tue, 10 Dec 2024 11:55:52 +0000 (11:55 +0000)
committerNick Porter <nick@portercomputing.co.uk>
Sun, 22 Dec 2024 13:56:57 +0000 (13:56 +0000)
Called after a TLS session is established, primarily intended for
logging.

share/dictionary/tls/dictionary.freeradius
src/lib/server/cf_file.c
src/lib/tls/attrs.h
src/lib/tls/base.c
src/lib/tls/conf-h
src/lib/tls/conf.c
src/lib/tls/session.c
src/process/tls/base.c

index f38e6744f8174135eec2606df547475f63d0d26e..d4159385145d852a8f2c9b7a9d6321c507f67a4d 100644 (file)
@@ -15,6 +15,7 @@ VALUE Packet-Type                     Store-Session           2
 VALUE  Packet-Type                     Clear-Session           3
 VALUE  Packet-Type                     Verify-Certificate      4
 VALUE  Packet-Type                     New-Session             5
+VALUE  Packet-Type                     Establish-Session       6
 
 #
 #  We use response packet types instead of rcodes so that
index 83d5d694257b28b3d349ae469ffb38658d8c56ea..10b5483361f542bc5c8170a9eddf0a614295cdcf 100644 (file)
@@ -2694,6 +2694,7 @@ alloc_section:
                    (strcmp(css->name1, "recv") == 0) ||
                    (strcmp(css->name1, "send") == 0) ||
                    (strcmp(css->name1, "store") == 0) ||
+                   (strcmp(css->name1, "establish") == 0) ||
                    (strcmp(css->name1, "verify") == 0)) {
                        css->unlang = CF_UNLANG_ALLOW;
                        css->allow_locals = true;
index 325c818bdedf6122b7bdc90b759f2d34f63a9c4d..46e8be1e445a961a24802100baddeefb73d579e7 100644 (file)
@@ -72,6 +72,7 @@ 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_new_session;
+extern fr_value_box_t const *enum_tls_packet_type_establish_session;
 
 extern fr_value_box_t const *enum_tls_packet_type_success;
 extern fr_value_box_t const *enum_tls_packet_type_failure;
index 48292f5faa6b5eb150ce0ee31b35c686adb61ffb..ec77743a029df3b522d25f96910e126c7b86d83c 100644 (file)
@@ -167,6 +167,7 @@ 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;
 fr_value_box_t const   *enum_tls_packet_type_new_session;
+fr_value_box_t const   *enum_tls_packet_type_establish_session;
 
 /*
  *     response types
@@ -182,6 +183,7 @@ fr_dict_enum_autoload_t tls_dict_enum[] = {
        { .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_new_session, .name = "New-Session", .attr = &attr_tls_packet_type },
+       { .out = &enum_tls_packet_type_establish_session, .name = "Establish-Session", .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 },
index 886329562a6fdf0cdea19bd1aadd07c953af2e53..e54b47cea78dc477848de34aa3ad4913a4e88926 100644 (file)
@@ -180,6 +180,7 @@ struct fr_tls_conf_s {
 
        bool            verify_certificate;             //!< Does the "verify certificate" section exist.
        bool            new_session;                    //!< Does the "new session" section exist.
+       bool            establish_session;              //!< Does the "establish session" section exist.
 };
 
 fr_tls_conf_t  *fr_tls_conf_alloc(TALLOC_CTX *ctx);
index a14411158ab9a65c2c80b5c85b48d3d2138c6489..76c45b1808ce09cc5903322d1d67e387b4f9d8b2 100644 (file)
@@ -253,6 +253,7 @@ static int tls_virtual_server_cf_parse(TALLOC_CTX *ctx, void *out, void *parent,
 
        conf->verify_certificate = cf_section_find(conf->virtual_server, "verify", "certificate") ? true : false;
        conf->new_session = cf_section_find(conf->virtual_server, "new", "session") ? true : false;
+       conf->establish_session = cf_section_find(conf->virtual_server, "establish", "session") ? true : false;
        return 0;
 }
 
index 1dc2b98def7fac37cccec677fd3dc81cae19f747..c4e8d02b13917a7065312e63ff00e2b3d297d0b1 100644 (file)
@@ -1131,6 +1131,54 @@ static void fr_tls_session_alert_send(request_t *request, fr_tls_session_t *sess
        session_msg_log(request, session, session->dirty_out.data, session->dirty_out.used);
 }
 
+/** Process the result of `establish session { ... }`
+ *
+ * As this is just a logging session, it's result doesn't affect the parent.
+ */
+static unlang_action_t tls_establish_session_result(UNUSED rlm_rcode_t *p_result, UNUSED int *priority,
+                                                   UNUSED request_t *request, UNUSED void *uctx)
+{
+       return UNLANG_ACTION_CALCULATE_RESULT;
+}
+
+/** Push an `establish session { ... }` call into the current request, using a subrequest
+ *
+ * @param[in] request          The current request.
+ * @param[in] conf             TLS configuration.
+ * @param[in] tls_session      The current TLS session.
+ * @return
+ *     - UNLANG_ACTION_PUSHED_CHILD on success.
+ *      - UNLANG_ACTION_FAIL on failure.
+ */
+static inline CC_HINT(always_inline)
+unlang_action_t tls_establish_session_push(request_t *request, fr_tls_conf_t *conf, fr_tls_session_t *tls_session)
+{
+       request_t       *child;
+       fr_pair_t       *vp;
+       unlang_action_t ua;
+
+       MEM(child = unlang_subrequest_alloc(request, dict_tls));
+       request = child;
+
+       /*
+        *      Setup the child request for reporting session
+        */
+       MEM(pair_prepend_request(&vp, attr_tls_packet_type) >= 0);
+       vp->vp_uint32 = enum_tls_packet_type_establish_session->vb_uint32;
+
+       /*
+        *      Allocate a child, and set it up to call
+        *      the TLS virtual server.
+        */
+       ua = fr_tls_call_push(child, tls_establish_session_result, conf, tls_session);
+       if (ua < 0) {
+               talloc_free(child);
+               return UNLANG_ACTION_FAIL;
+       }
+
+       return ua;
+}
+
 /** Finish off a handshake round, possibly adding attributes to the request
  *
  */
@@ -1270,6 +1318,10 @@ static unlang_action_t tls_session_async_handshake_done_round(UNUSED rlm_rcode_t
 
        tls_session->result = FR_TLS_RESULT_SUCCESS;
        fr_tls_session_request_unbind(tls_session->ssl);
+       if (SSL_is_init_finished(tls_session->ssl)) {
+               fr_tls_conf_t   *conf = fr_tls_session_conf(tls_session->ssl);
+               if (conf->establish_session) return tls_establish_session_push(request, conf, tls_session);
+       }
        return UNLANG_ACTION_CALCULATE_RESULT;
 }
 
index 599be6be729cb6836090b7212e67c161259544ab..ca2a30ac23c5886dfb9a9cfe3551840198c9b6cb 100644 (file)
@@ -47,6 +47,7 @@ typedef struct {
        CONF_SECTION    *clear_session;
        CONF_SECTION    *verify_certificate;
        CONF_SECTION    *new_session;
+       CONF_SECTION    *establish_session;
 } process_tls_sections_t;
 
 typedef struct {
@@ -147,6 +148,23 @@ static fr_process_state_t const process_state[] = {
                .resume = resume_recv_no_send,
                .section_offset = PROCESS_CONF_OFFSET(new_session),
        },
+       [FR_PACKET_TYPE_VALUE_ESTABLISH_SESSION] = {
+               .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_REJECT] =   FR_PACKET_TYPE_VALUE_FAILURE,
+                       [RLM_MODULE_FAIL] =     FR_PACKET_TYPE_VALUE_FAILURE,
+                       [RLM_MODULE_INVALID] =  FR_PACKET_TYPE_VALUE_FAILURE,
+                       [RLM_MODULE_DISALLOW] = FR_PACKET_TYPE_VALUE_FAILURE,
+                       [RLM_MODULE_NOTFOUND] = FR_PACKET_TYPE_VALUE_NOTFOUND,
+               },
+               .rcode = RLM_MODULE_NOOP,
+               .recv = recv_generic,
+               .resume = resume_recv_no_send,
+               .section_offset = PROCESS_CONF_OFFSET(establish_session),
+       },
 };
 
 static unlang_action_t mod_process(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
@@ -194,6 +212,11 @@ static const virtual_server_compile_t compile_list[] = {
                .actions = &mod_actions_authorize,
                .offset = PROCESS_CONF_OFFSET(new_session)
        },
+       {
+               .section = SECTION_NAME("establish", "session"),
+               .actions = &mod_actions_authorize,
+               .offset = PROCESS_CONF_OFFSET(establish_session)
+       },
        COMPILE_TERMINATOR
 };