25RCSID(
"$Id: 38d2e911cfd420f98618776f2d18a89b984b025a $")
27#include <freeradius-devel/crl/crl.h>
28#include <freeradius-devel/server/base.h>
29#include <freeradius-devel/server/module_rlm.h>
30#include <freeradius-devel/io/coord_pair.h>
32#include <freeradius-devel/tls/strerror.h>
33#include <freeradius-devel/tls/utils.h>
35#include <freeradius-devel/unlang/xlat_func.h>
37#include <openssl/x509v3.h>
129 fr_value_box_list_head_t *
cdp;
146 .pair.dflt =
"session-state.TLS-Certificate.Serial", .pair.dflt_quote =
T_BARE_WORD },
148 .pair.dflt =
"session-state.TLS-Certificate.X509v3-CRL-Distribution-Points[*]", .pair.dflt_quote =
T_BARE_WORD },
153static int8_t crl_cmp(
void const *a,
void const *b)
161static int8_t crl_pending_cmp(
void const *a,
void const *b)
169static int8_t crl_fail_cmp(
void const *a,
void const *b)
200 TALLOC_CTX *local = talloc_new(NULL);
248 X509_REVOKED *revoked;
249 ASN1_INTEGER *asn1_serial = NULL;
252 asn1_serial = d2i_ASN1_INTEGER(NULL, (
unsigned char const **)&serial, talloc_array_length(serial));
253 ret = X509_CRL_get0_by_serial(crl_entry->
crl, &revoked, asn1_serial);
254 ASN1_INTEGER_free(asn1_serial);
258 RDEBUG3(
"Certificate not in CRL");
289 while ((vb = fr_value_box_list_next(&(*found)->delta_urls, vb))) {
290 find.
cdp_url = vb->vb_strvalue;
293 ret = crl_check_entry(delta, request, serial);
307 return crl_check_entry(*found, request, serial);
312 X509_CRL_free(crl_entry->
crl);
329 TALLOC_CTX *local = talloc_new(NULL);
381 fr_value_box_list_t missing;
383 char const *base_url = NULL;
388 fr_value_box_list_init(&missing);
390 while ((cdp = fr_value_box_list_next(env->
cdp, cdp))) {
391 switch (crl_check_serial(&t->
crls, request, cdp->vb_strvalue, env->
serial.vb_octets, &found)) {
404 fr_value_box_list_insert_tail(&missing, uri);
409 fr_value_box_list_talloc_free(&missing);
410 while ((vb = fr_value_box_list_next(&found->
delta_urls, vb))) {
412 fr_value_box_list_insert_tail(&missing, uri);
414 base_url = cdp->vb_strvalue;
422 .
cdp_url = fr_value_box_list_head(&missing)->vb_strvalue
433 fr_value_box_list_talloc_free(&missing);
440 ret = crl_fetch_start(
inst, t, &missing, base_url);
442 fr_value_box_list_talloc_free(&missing);
457 RDEBUG3(
"Yielding request until CRL fetching completed");
491 ERROR(
"Missing URL");
503 ERROR(
"No CRL data");
513 fr_value_box_list_init(&crl_entry->
delta_urls);
518 talloc_set_destructor(crl_entry, _crl_entry_free);
520 X509_CRL_free(crl_entry->
crl);
521 fr_value_box_list_talloc_free(&crl_entry->
delta_urls);
524 data = crl->vp_octets;
525 crl_entry->
crl = d2i_X509_CRL(NULL, (
const unsigned char **)&
data, crl->vp_size);
527 ERROR(
"Failed to parse CRL");
533 DEBUG3(
"CRL %pP refreshed", crl);
539 fr_value_box_list_insert_tail(&crl_entry->
delta_urls, vb);
542 crl_pending_resume(thread);
569 crl_pending_resume(thread);
590 if (!crl_entry)
return;
598 find.
cdp_url = delta->vb_strvalue;
600 if (!delta_entry)
continue;
602 WARN(
"Delta CRL %s expired", delta_entry->
cdp_url);
632 ERROR(
"Failed to attach to coordinator");
642 if (!
inst->urls)
return 0;
644 for (i = 0; i < talloc_array_length(
inst->urls); i++) {
645 fr_value_box_list_t list;
648 DEBUG2(
"Pre-fetching CRL from %s",
inst->urls[i]);
649 fr_value_box_list_init(&list);
652 fr_value_box_list_insert_head(&list, &vb);
653 if (crl_fetch_start(
inst, t, &list, NULL) < 0) {
654 ERROR(
"Failed to initiate fetch for %s",
inst->urls[i]);
666 if (!t->
cw)
return 0;
720 .worker_cb = worker_pair_callbacks,
726 if (!
inst->coord_pair_reg)
return -1;
733 .coord_cb = coord_callbacks,
734 .worker_cb = worker_callbacks,
738 if (!
inst->coord_reg)
return -1;
759 .coord_attach = mod_coord_attach,
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
@ UNLANG_ACTION_YIELD
Temporarily pause execution until an event occurs.
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
#define CALL_ENV_TERMINATOR
#define FR_CALL_ENV_METHOD_OUT(_inst)
Helper macro for populating the size/type fields of a call_env_method_t from the output structure typ...
call_env_parser_t const * env
Parsing rules for call method env.
@ CALL_ENV_FLAG_SINGLE
If the tmpl produces more than one box this is an error.
@ CALL_ENV_FLAG_ATTRIBUTE
Tmpl MUST contain an attribute reference.
@ CALL_ENV_FLAG_MULTI
Multiple instances of the conf pairs are allowed.
@ CALL_ENV_FLAG_REQUIRED
Associated conf pair or section is required.
@ CALL_ENV_FLAG_BARE_WORD_ATTRIBUTE
bare words are treated as an attribute, but strings may be xlats.
@ CALL_ENV_FLAG_NULLABLE
Tmpl expansions are allowed to produce no output.
#define FR_CALL_ENV_OFFSET(_name, _cast_type, _flags, _struct, _field)
Specify a call_env_parser_t which writes out runtime results to the specified field.
#define CONF_PARSER_TERMINATOR
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
#define FR_CONF_OFFSET_FLAGS(_name, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
@ CONF_FLAG_MULTI
CONF_PAIR can have multiple copies.
Defines a CONF_PAIR to C data type mapping.
#define cf_log_err(_cf, _fmt,...)
fr_coord_reg_t * fr_coord_register(TALLOC_CTX *ctx, fr_coord_reg_ctx_t *reg_ctx)
Register a coordinator.
fr_coord_worker_t * fr_coord_attach(TALLOC_CTX *ctx, fr_event_list_t *el, fr_coord_reg_t *coord_reg)
Attach a worker to a coordinator.
void fr_coord_deregister(fr_coord_reg_t *coord_reg)
De-register a coordinator.
int fr_coord_detach(fr_coord_worker_t *cw, bool exiting)
Signal a coordinator that a worker wants to detach.
A coordinator registration.
The worker end of worker <-> coordinator communication.
#define FR_COORD_CALLBACK_TERMINATOR
int fr_worker_to_coord_pair_send(fr_coord_worker_t *cw, fr_coord_pair_reg_t *coord_pair_reg, fr_pair_list_t *list)
Send a pair list from a worker to a coordinator.
fr_coord_pair_reg_t * fr_coord_pair_register(TALLOC_CTX *ctx, fr_coord_pair_reg_ctx_t *reg_ctx)
Register a set of callbacks for pair list based coordinator messages.
uint32_t packet_type
Packet type value for this callback.
#define FR_COORD_WORKER_PAIR_CALLBACK(_id)
Set callback for handling coordinator -> worker pair list data.
#define FR_COORD_PAIR_CALLBACK(_id)
Set callback for handling worker -> coordinator pair list data.
struct fr_coord_pair_reg_s fr_coord_pair_reg_t
#define FR_COORD_PAIR_CB_CTX_SET(_in_cb, _out_cb, _reg)
Set up ctx on pair list callbacks.
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
#define DICT_AUTOLOAD_TERMINATOR
Specifies an attribute which must be present for the module to function.
Specifies a dictionary which must be loaded/loadable for the module to function.
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
void unlang_interpret_mark_runnable(request_t *request)
Mark a request as resumable.
#define REDEBUG2(fmt,...)
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_BOOL
A truth value.
@ FR_TYPE_OCTETS
Raw octets.
void * env_data
Per call environment data.
module_instance_t const * mi
Instance of the module being instantiated.
void * thread
Thread specific instance data.
void * rctx
Resume ctx that a module previously set.
fr_event_list_t * el
Event list to register any IO handlers and timers against.
module_instance_t * mi
Module instance to detach.
void * thread
Thread instance data.
module_instance_t const * mi
Instance of the module being instantiated.
module_instance_t * mi
Instance of the module being instantiated.
Temporary structure to hold arguments for module calls.
Temporary structure to hold arguments for detach calls.
Temporary structure to hold arguments for instantiation calls.
Temporary structure to hold arguments for thread_instantiation calls.
xlat_t * module_rlm_xlat_register(TALLOC_CTX *ctx, module_inst_ctx_t const *mctx, char const *name, xlat_func_t func, fr_type_t return_type)
module_t common
Common fields presented by all modules.
int fr_pair_append_by_da(TALLOC_CTX *ctx, fr_pair_t **out, fr_pair_list_t *list, fr_dict_attr_t const *da)
Alloc a new fr_pair_t (and append)
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.
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
static const conf_parser_t config[]
static char const * url[FR_RADIUS_FAIL_MAX+1]
void * fr_rb_iter_init_inorder(fr_rb_tree_t *tree, fr_rb_iter_inorder_t *iter)
Initialise an in-order iterator.
void fr_rb_iter_delete_inorder(fr_rb_tree_t *tree, fr_rb_iter_inorder_t *iter)
Remove the current node from the tree.
void * fr_rb_remove(fr_rb_tree_t *tree, void const *data)
Remove an entry from the tree, without freeing the data.
void * fr_rb_find(fr_rb_tree_t const *tree, void const *data)
Find an element in the tree, returning the data, not the node.
bool fr_rb_insert(fr_rb_tree_t *tree, void const *data)
Insert data into a tree.
bool fr_rb_delete(fr_rb_tree_t *tree, void const *data)
Remove node and free data (if a free function was specified)
void * fr_rb_iter_next_inorder(UNUSED fr_rb_tree_t *tree, fr_rb_iter_inorder_t *iter)
Return the next node.
#define fr_rb_inline_init(_tree, _type, _field, _data_cmp, _data_free)
Initialises a red black tree.
Iterator structure for in-order traversal of an rbtree.
The main red black tree structure.
#define RETURN_UNLANG_FAIL
#define RETURN_UNLANG_REJECT
static int mod_detach(module_detach_ctx_t const *mctx)
static int mod_bootstrap(module_inst_ctx_t const *mctx)
static int mod_thread_instantiate(module_thread_inst_ctx_t const *mctx)
static int mod_thread_detach(module_thread_inst_ctx_t const *mctx)
static fr_dict_attr_t const * attr_delta_crl
fr_value_box_list_t crl_data
Data from CRL expansion.
static fr_dict_attr_t const * attr_packet_type
fr_rb_node_t node
Node in the tree of failures.
fr_value_box_list_t delta_urls
URLs from which a delta CRL can be retrieved.
fr_coord_pair_reg_t * coord_pair_reg
coord_pair registration for fetching CRLs.
fr_coord_reg_t * coord_reg
coord registration for fetching CRLs.
crl_check_status_t
A status used to track which CRL is being checked.
@ CRL_CHECK_BASE
The base CRL is being checked.
@ CRL_CHECK_DELTA
The delta CRL exists and is being checked.
@ CRL_CHECK_FETCH_DELTA
The delta CRL is being fetched.
fr_value_box_t serial
The serial to check.
@ CRL_MISSING_DELTA
Need to load a delta CRL to supplement this CRL.
@ CRL_ENTRY_FOUND
Serial was found in this CRL.
@ CRL_ENTRY_REMOVED
Serial was "un-revoked" in this delta CRL.
@ CRL_ERROR
Unspecified error ocurred.
@ CRL_NOT_FOUND
No CRL found, need to load it from the CDP URL.
@ CRL_ENTRY_NOT_FOUND
Serial not found in this CRL.
fr_value_box_t * cdp_url
The URL we're currently attempting to load.
fr_dict_attr_autoload_t rlm_crl_dict_attr[]
char const * cdp_url
The URL which failed to fetch.
fr_coord_worker_t * cw
Worker side of coordinator communication.
static fr_dict_attr_t const * attr_base_crl
fr_time_t fail_time
When did the failure occur.
fr_rb_node_t node
The node in the tree.
char const * cdp_url
The URL of the CRL.
fr_rb_tree_t fails
Recent CRLs which have failed to fetch.
fr_value_box_list_t missing_crls
CRLs missing from the tree.
rlm_crl_coord_callback_t
Callback IDs used by CRL coordinator calls.
@ CRL_COORD_PAIR_CALLBACK_ID
fr_rb_tree_t crls
CRLs fetched from the coordinator.
static fr_dict_attr_t const * attr_crl_cdp_url
crl_entry_t * base_crl
The base CRL relating to the delta currently being fetched.
static fr_dict_t const * dict_crl
char const ** urls
Initial list of URLs to fetch.
fr_rb_tree_t pending
Requests yielded while the CRL is being fetched.
fr_dict_autoload_t rlm_crl_dict[]
fr_value_box_list_head_t * cdp
The CRL distribution points.
fr_time_delta_t retry_delay
Time to hold off between CRL fetching failures.
static int mod_instantiate(module_inst_ctx_t const *mctx)
Instantiate the module.
static fr_dict_attr_t const * attr_crl_data
static conf_parser_t module_config[]
crl_check_status_t status
Status of the current CRL check.
A single CRL in the thread specific list of CRLs.
Structure to record recent fetch failures.
Structure to record a request which is waiting for CRL fetching to complete.
Thread specific structure to hold requests awaiting CRL fetching.
int fr_schedule_worker_id(void)
Return the worker id for the current thread.
#define SECTION_NAME(_name1, _name2)
Define a section name consisting of a verb and a noun.
#define MODULE_THREAD_INST(_ctype)
char const * name
Instance name e.g. user_database.
CONF_SECTION * conf
Module's instance configuration.
size_t inst_size
Size of the module's instance data.
void * data
Module's instance data.
void * boot
Data allocated during the boostrap phase.
#define MODULE_BINDING_TERMINATOR
Terminate a module binding list.
Named methods exported by a module.
fr_signal_t
Signals that can be generated/processed by request signal handlers.
@ FR_SIGNAL_CANCEL
Request has been cancelled.
unlang_action_t unlang_module_yield(request_t *request, module_method_t resume, unlang_module_signal_t signal, fr_signal_t sigmask, void *rctx)
Yield a request back to the interpreter from within a module.
eap_aka_sim_process_conf_t * inst
Stores an attribute, a value and various bits of other data.
#define talloc_get_type_abort_const
#define talloc_strdup(_ctx, _str)
#define fr_time_add(_a, _b)
Add a time/time delta together.
#define fr_time_gt(_a, _b)
A time delta, a difference in time measured in nanoseconds.
#define XLAT_ARGS(_list,...)
Populate local variables with value boxes from the input list.
unsigned int required
Argument must be present, and non-empty.
#define XLAT_ARG_PARSER_TERMINATOR
@ XLAT_ACTION_FAIL
An xlat function failed.
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
Definition for a single argument consumed by an xlat function.
#define fr_pair_list_append_by_da(_ctx, _vp, _list, _attr, _val, _tainted)
Append a pair to a list, assigning its value.
int fr_value_box_copy(TALLOC_CTX *ctx, fr_value_box_t *dst, const fr_value_box_t *src)
Copy value data verbatim duplicating any buffers.
int fr_value_box_strdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Copy a nul terminated string to a fr_value_box_t.
void fr_value_box_strdup_shallow(fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Assign a buffer containing a nul terminated string to a box, but don't copy it.
#define fr_value_box_alloc(_ctx, _type, _enumv)
Allocate a value box of a specific type.
static fr_value_box_t * fr_value_box_acopy(TALLOC_CTX *ctx, fr_value_box_t const *src)
Copy an existing box, allocating a new box to hold its contents.
#define fr_value_box_alloc_null(_ctx)
Allocate a value box for later use with a value assignment function.
#define fr_value_box_init(_vb, _type, _enumv, _tainted)
Initialise a fr_value_box_t.
#define fr_value_box_list_foreach(_list_head, _iter)
static size_t char ** out
module_ctx_t const * mctx
Synthesised module calling ctx.
int xlat_func_args_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the arguments of an xlat.