]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Send CRL-Expire to worker if refresh of expired CRL fails
authorNick Porter <nick@portercomputing.co.uk>
Mon, 6 Apr 2026 10:38:38 +0000 (11:38 +0100)
committerNick Porter <nick@portercomputing.co.uk>
Mon, 6 Apr 2026 12:15:40 +0000 (13:15 +0100)
and expired CRLs are not allowed.

share/dictionary/crl/dictionary.freeradius
src/modules/rlm_crl/rlm_crl.c
src/process/crl/base.c
src/protocols/crl/crl.h

index 45ca080062b40873ce7607383ce120886774560b..02bbb722516df1177e574689ec447cf3bc080ee4 100644 (file)
@@ -14,6 +14,7 @@ VALUE Packet-Type                     CRL-Fetch               1
 VALUE  Packet-Type                     CRL-Refresh             2
 VALUE  Packet-Type                     Fetch-OK                3
 VALUE  Packet-Type                     Fetch-Fail              4
+VALUE  Packet-Type                     CRL-Expire              5
 VALUE  Packet-Type                     Do-Not-Respond          255
 
 ATTRIBUTE      CDP-URL                                 3       string
index 5acb0c18b7fc3051172e67481b00efe8ca42bd10..38d2e911cfd420f98618776f2d18a89b984b025a 100644 (file)
@@ -569,6 +569,46 @@ static void recv_crl_fail(UNUSED fr_coord_worker_t *cw, UNUSED fr_coord_pair_reg
        crl_pending_resume(thread);
 }
 
+/** Callback for worker receiving CRL-Expire packet from coordinator
+ */
+static void recv_crl_expire(UNUSED fr_coord_worker_t *cw, UNUSED fr_coord_pair_reg_t *coord_pair_reg,
+                           fr_pair_list_t const *list, UNUSED fr_time_t now, module_ctx_t *mctx, UNUSED void *uctx)
+{
+       fr_pair_t               *vp;
+       rlm_crl_thread_t        *thread = talloc_get_type_abort(mctx->thread, rlm_crl_thread_t);
+       crl_entry_t             *crl_entry, find;
+
+       vp = fr_pair_find_by_da(list, NULL, attr_crl_cdp_url);
+       if (!vp) return;
+
+       find = (crl_entry_t) {
+               .cdp_url = vp->vp_strvalue
+       };
+
+       crl_entry = fr_rb_find(&thread->crls, &find);
+
+       if (!crl_entry) return;
+
+       /*
+        *      If the expired CRL has any deltas, remove them as well.
+        */
+       fr_value_box_list_foreach(&crl_entry->delta_urls, delta) {
+               crl_entry_t     *delta_entry;
+
+               find.cdp_url = delta->vb_strvalue;
+               delta_entry = fr_rb_find(&thread->crls, &find);
+               if (!delta_entry) continue;
+
+               WARN("Delta CRL %s expired", delta_entry->cdp_url);
+               fr_rb_remove(&thread->crls, delta_entry);
+               talloc_free(delta_entry);
+       }
+
+       WARN("CRL %s expired", crl_entry->cdp_url);
+       fr_rb_remove(&thread->crls, crl_entry);
+       talloc_free(crl_entry);
+}
+
 static int mod_thread_instantiate(module_thread_inst_ctx_t const *mctx)
 {
        rlm_crl_thread_t        *t = talloc_get_type_abort(mctx->thread, rlm_crl_thread_t);
@@ -662,6 +702,7 @@ static fr_coord_worker_cb_reg_t worker_callbacks[] = {
 static fr_coord_worker_pair_cb_reg_t worker_pair_callbacks[] = {
        { .packet_type = FR_CRL_FETCH_OK, .callback = recv_crl_ok },
        { .packet_type = FR_CRL_FETCH_FAIL, .callback = recv_crl_fail },
+       { .packet_type = FR_CRL_CRL_EXPIRE, .callback = recv_crl_expire },
        FR_COORD_CALLBACK_TERMINATOR
 };
 #endif
index 88a49826881bdd8db2a852bd44e8ab6366dc5db2..081f116cfa4b120119cebb92965e2bb273684649 100644 (file)
@@ -756,14 +756,49 @@ RESUME_FLAG(send_crl_ok, UNUSED,)
 RESUME_FLAG(send_crl_fail, UNUSED,)
 {
        process_crl_t           *inst = talloc_get_type_abort(mctx->mi->data, process_crl_t);
+       process_thread_crl_t    *thread = talloc_get_type_abort(mctx->thread, process_thread_crl_t);
        process_crl_rctx_t      *rctx = talloc_get_type_abort(mctx->rctx, process_crl_rctx_t);
        fr_pair_t               *vp;
 
-       /*
-        *      Refresh requests are local to the coordinator, so there
-        *      is nothing to send back on a failure.
-        */
-       if (rctx->refresh) return UNLANG_ACTION_CALCULATE_RESULT;
+       if (rctx->refresh) {
+               crl_fetching_entry_remove(&inst->mutable->fetching, rctx->cdp_url);
+
+               /*
+                *      Set up retry of failed refresh.
+                */
+               RDEBUG2("Refresh of CRL from %s will retry in %pVs", rctx->cdp_url, fr_box_time_delta(inst->retry_delay));
+
+               if (fr_timer_in(rctx->crl_entry, thread->el->tl, &rctx->crl_entry->ev, inst->retry_delay,
+                               false, crl_refresh_event, rctx->crl_entry) <0) {
+                       RERROR("Failed to set timer to retry CRL fetch");
+               }
+
+               /*
+                *      Refresh requests are local to the coordinator, so there
+                *      is nothing to send back on a failure, unless the CRL has
+                *      expired and expired CRLs are not allowed.
+                */
+               if (inst->allow_expired || fr_time_gt(fr_time_from_sec(rctx->crl_entry->next_update),
+                                                     fr_time_from_sec(time(NULL)))) {
+                       return UNLANG_ACTION_CALCULATE_RESULT;
+               }
+
+               /*
+                *      A refresh failed on an expired CRL, notify all workers with a CRL-Expire reply.
+                */
+               fr_pair_list_free(&request->reply_pairs);
+               if (fr_pair_append_by_da(request->reply_ctx, &vp, &request->reply_pairs,
+                                        attr_packet_type) < 0) RETURN_UNLANG_FAIL;
+               vp->vp_uint32 = FR_CRL_CRL_EXPIRE;
+
+               if (fr_pair_append_by_da(request->reply_ctx, &vp, &request->reply_pairs,
+                                        attr_crl_cdp_url) < 0) RETURN_UNLANG_FAIL;
+               fr_value_box_strdup(vp, &vp->data, NULL, rctx->cdp_url, false);
+
+               fr_coord_to_worker_reply_broadcast(request);
+
+               return UNLANG_ACTION_CALCULATE_RESULT;
+       }
 
        /*
         *      The fetch failed, ensure we don't send CRL data back
index 0aece6a2173d54453961411f6afada8a2ea162b5..e019215aee240f0ca161f9b175f99ef1f81f7110 100644 (file)
@@ -33,6 +33,7 @@ typedef enum {
        FR_CRL_CRL_REFRESH,
        FR_CRL_FETCH_OK,
        FR_CRL_FETCH_FAIL,
+       FR_CRL_CRL_EXPIRE,
        FR_CRL_CODE_MAX,
        FR_CRL_DO_NOT_RESPOND = 255
 } fr_crl_packet_code_t;