25#include <freeradius-devel/crl/crl.h>
26#include <freeradius-devel/io/coord_pair.h>
27#include <freeradius-devel/server/main_config.h>
28#include <freeradius-devel/server/protocol.h>
29#include <freeradius-devel/tls/strerror.h>
30#include <freeradius-devel/tls/utils.h>
31#include <freeradius-devel/unlang/interpret.h>
32#include <freeradius-devel/util/debug.h>
34#include <openssl/x509.h>
35#include <openssl/x509v3.h>
36#include <openssl/asn1.h>
80} process_crl_sections_t;
85} process_crl_mutable_t;
88 process_crl_sections_t sections;
92 bool force_refresh_is_set;
94 bool force_delta_refresh_is_set;
101 bool allow_not_yet_valid;
103 X509_STORE *verify_store;
105 process_crl_mutable_t *
mutable;
110} process_thread_crl_t;
115 {
FR_CONF_OFFSET(
"early_refresh", process_crl_t, early_refresh) },
116 {
FR_CONF_OFFSET(
"retry_delay", process_crl_t, retry_delay), .dflt =
"30s" },
119 {
FR_CONF_OFFSET(
"allow_expired", process_crl_t, allow_expired) },
120 {
FR_CONF_OFFSET(
"allow_not_yet_valid", process_crl_t, allow_not_yet_valid) },
137 ASN1_INTEGER *crl_num;
141 fr_value_box_list_t delta_urls;
142 char const *base_url;
163} crl_pending_request_t;
167static int8_t crl_cmp(
void const *a,
void const *b)
186#define FR_CRL_PACKET_CODE_VALID(_code) (((_code) > 0) && ((_code) < FR_CRL_CODE_MAX))
187#define FR_CRL_PROCESS_CODE_VALID(_code) (FR_CRL_PACKET_CODE_VALID(_code) || (_code == FR_CRL_DO_NOT_RESPOND))
189#define PROCESS_PACKET_TYPE fr_crl_packet_code_t
190#define PROCESS_CODE_MAX FR_CRL_CODE_MAX
191#define PROCESS_CODE_DO_NOT_RESPOND FR_CRL_DO_NOT_RESPOND
192#define PROCESS_PACKET_CODE_VALID FR_CRL_PROCESS_CODE_VALID
193#define PROCESS_INST process_crl_t
194#define PROCESS_RCTX process_crl_rctx_t
196#include <freeradius-devel/server/process.h>
206 process_crl_t *
inst = talloc_get_type_abort(mctx->
mi->
data, process_crl_t);
214 if (strcmp(fetching->cdp_url,
vp->vp_strvalue) == 0) {
215 if (rctx->worker_id >= 0) fetching->workers[rctx->worker_id] =
true;
216 RDEBUG2(
"CRL already being fetched");
236 MEM(fetch = talloc(
inst->mutable, crl_fetch_t));
237 fetch->cdp_url = rctx->cdp_url;
241 return CALL_RECV(generic);
258 ASN1_INTEGER_get_uint64(&
vp->vp_uint64, crl_entry->crl_num);
261 if (crl_entry->type == CRL_TYPE_BASE) {
273 if (
fr_pair_append_by_da(request->reply_ctx, &
vp, &request->reply_pairs, attr_last_update) < 0)
return -1;
277 if (
fr_pair_append_by_da(request->reply_ctx, &
vp, &request->reply_pairs, attr_next_update) < 0)
return -1;
293 process_crl_t *
inst = talloc_get_type_abort(mctx->
mi->
data, process_crl_t);
294 process_crl_rctx_t *rctx = talloc_get_type_abort(mctx->
rctx, process_crl_rctx_t);
299 rctx->worker_id =
vp->vp_int32;
305 rctx->crl_entry = crl_entry =
fr_rb_find(&
inst->mutable->crls, &find);
317 if (crl_build_reply(request, crl_entry) < 0)
return CALL_SEND_TYPE(
FR_CRL_FETCH_FAIL);
323 return fetch_setup_common(p_result, mctx, request,
vp, rctx);
332 process_crl_t *
inst = talloc_get_type_abort(mctx->
mi->
data, process_crl_t);
333 process_crl_rctx_t *rctx = talloc_get_type_abort(mctx->
rctx, process_crl_rctx_t);
341 if (rctx->crl_entry) rctx->refresh =
true;
343 return fetch_setup_common(p_result, mctx, request,
vp, rctx);
350 if (to_free->crl_num) ASN1_INTEGER_free(to_free->crl_num);
360 if ((to_free->type == CRL_TYPE_BASE) && fr_value_box_list_initialised(&to_free->
delta_urls)) {
364 find.
cdp_url = delta->vb_strvalue;
365 delta_crl =
fr_rb_find(&to_free->inst->mutable->crls, &find);
366 if (!delta_crl)
continue;
383 TALLOC_CTX *local = talloc_new(NULL);
398 if (crl_entry->type == CRL_TYPE_DELTA) {
404 ERROR(
"Failed to initialise CRL refresh request");
405 if (
fr_timer_in(crl_entry, tl, &crl_entry->ev, crl_entry->inst->retry_delay,
false,
406 crl_refresh_event, crl_entry) <0) {
407 ERROR(
"Failed to set timer to retry CRL refresh");
414static inline void crl_fetching_entry_remove(
fr_dlist_head_t *fetching,
char const *cdp_url) {
416 if (strcmp(fetch->cdp_url, cdp_url) == 0) {
426 process_crl_t *
inst = talloc_get_type_abort(mctx->
mi->
data, process_crl_t);
427 process_thread_crl_t *thread = talloc_get_type_abort(mctx->
thread, process_thread_crl_t);
428 process_crl_rctx_t *rctx = talloc_get_type_abort(mctx->
rctx, process_crl_rctx_t);
433 X509_STORE_CTX *verify_ctx = NULL;
436 STACK_OF(DIST_POINT) *dps;
441 switch (RESULT_RCODE) {
443 return CALL_RESUME(recv_generic);
461 data = crl_data->vp_octets;
462 crl = d2i_X509_CRL(NULL, (
const unsigned char **)&
data, crl_data->vp_size);
464 fr_tls_strerror_printf(
"Failed to parse CRL from %s", rctx->cdp_url);
468 verify_ctx = X509_STORE_CTX_new();
469 if (!verify_ctx || !X509_STORE_CTX_init(verify_ctx,
inst->verify_store, NULL, NULL)) {
470 fr_tls_strerror_printf(
"Error initialising X509 store");
472 if (verify_ctx) X509_STORE_CTX_free(verify_ctx);
473 RPERROR(
"Error verifying CRL");
479 xobj = X509_STORE_CTX_get_obj_by_subject(verify_ctx, X509_LU_X509, X509_CRL_get_issuer(crl));
481 fr_tls_strerror_printf(
"CRL issuer certificate not in trusted store");
484 pkey = X509_get_pubkey(X509_OBJECT_get0_X509(xobj));
485 X509_OBJECT_free(xobj);
487 fr_tls_strerror_printf(
"Error getting CRL issuer public key");
490 i = X509_CRL_verify(crl, pkey);
494 fr_tls_strerror_printf(
"Could not verify CRL signature");
498 fr_tls_strerror_printf(
"CRL certificate signature failed");
506 crl_entry->inst =
inst;
511 crl_entry->type = rctx->base_crl ? CRL_TYPE_DELTA : CRL_TYPE_BASE;
512 talloc_set_destructor(crl_entry, _crl_entry_free);
515 RPERROR(
"Failed to parse nextUpdate from CRL");
525 crl_entry->crl_num = X509_CRL_get_ext_d2i(crl, NID_crl_number, &i, NULL);
526 if (!crl_entry->crl_num) {
527 fr_tls_strerror_printf(
"Missing CRL number");
534 if (rctx->crl_entry) {
535 if (ASN1_INTEGER_cmp(crl_entry->crl_num, rctx->crl_entry->crl_num) == 0) {
537 ASN1_INTEGER_get_uint64(&new_num, crl_entry->crl_num);
538 RDEBUG3(
"Refresh returned the same CRL number (%"PRIu64
") as the existing entry", new_num);
541 if (ASN1_INTEGER_cmp(crl_entry->crl_num, rctx->crl_entry->crl_num) < 0) {
542 uint64_t old_num, new_num;
543 ASN1_INTEGER_get_uint64(&old_num, rctx->crl_entry->crl_num);
544 ASN1_INTEGER_get_uint64(&new_num, crl_entry->crl_num);
545 RERROR(
"Got CRL number %"PRIu64
" which is less than current number %"PRIu64,
548 crl_fetching_entry_remove(&
inst->mutable->fetching, rctx->cdp_url);
550 crl_entry = rctx->crl_entry;
561 if (crl_build_reply(request, crl_entry) < 0)
goto error;
571 TALLOC_FREE(rctx->crl_entry);
579 crl_entry->crl_data =
talloc_typed_memdup(crl_entry, crl_data->vp_octets, crl_data->vp_length);
585 if (crl_entry->type == CRL_TYPE_DELTA) {
586 ASN1_INTEGER *base_num = X509_CRL_get_ext_d2i(crl, NID_delta_crl, &i, NULL);
588#ifdef __clang_analyzer__
593 if (
unlikely(!rctx->base_crl))
goto error;
597 RERROR(
"Delta CRL missing Delta CRL Indicator extension");
600 if (ASN1_INTEGER_cmp(base_num, rctx->base_crl->crl_num) > 0) {
601 uint64_t delta_base, crl_num;
602 ASN1_INTEGER_get_uint64(&delta_base, base_num);
603 ASN1_INTEGER_get_uint64(&crl_num, rctx->base_crl->crl_num);
604 RERROR(
"Delta CRL referrs to base CRL number %"PRIu64
", current base is %"PRIu64,
605 delta_base, crl_num);
606 ASN1_INTEGER_free(base_num);
609 ASN1_INTEGER_free(base_num);
610 if (ASN1_INTEGER_cmp(crl_entry->crl_num, rctx->base_crl->crl_num) < 0) {
611 uint64_t delta_num, crl_num;
612 ASN1_INTEGER_get_uint64(&delta_num, crl_entry->crl_num);
613 ASN1_INTEGER_get_uint64(&crl_num, rctx->base_crl->crl_num);
614 RERROR(
"Delta CRL number %"PRIu64
" is less than base CRL number %"PRIu64, delta_num, crl_num);
617 crl_entry->base_url =
talloc_strdup(crl_entry, rctx->base_crl->cdp_url);
621 RPERROR(
"Failed to parse lastUpdate from CRL");
634 if ((crl_entry->type == CRL_TYPE_BASE) && (dps = X509_CRL_get_ext_d2i(crl, NID_freshest_crl, NULL, NULL))) {
636 STACK_OF(GENERAL_NAME) *
names;
641 fr_value_box_list_init(&crl_entry->
delta_urls);
642 for (i = 0; i < sk_DIST_POINT_num(dps); i++) {
643 dp = sk_DIST_POINT_value(dps, i);
644 names = dp->distpoint->name.fullname;
645 for (j = 0; j < sk_GENERAL_NAME_num(
names); j++) {
647 if (
name->type != GEN_URI)
continue;
650 (
char const *)ASN1_STRING_get0_data(
name->d.uniformResourceIdentifier),
651 ASN1_STRING_length(
name->d.uniformResourceIdentifier),
true);
652 RDEBUG3(
"CRL references delta URI %pV", vb);
653 fr_value_box_list_insert_tail(&crl_entry->
delta_urls, vb);
656 CRL_DIST_POINTS_free(dps);
663 if (fr_value_box_list_num_elements(&crl_entry->
delta_urls) > 0) {
666 TALLOC_CTX *local = talloc_new(NULL);
670 if (!
vp)
goto free_local;
679 false) < 0))
goto free_local;
682 RERROR(
"Failed to start fetch of delta CRL");
691 RERROR(
"Failed storing CRL");
695 if (crl_build_reply(request, crl_entry) < 0)
goto error;
703 if (rctx->base_crl &&
inst->force_delta_refresh_is_set) {
706 if (
inst->force_refresh_is_set &&
718 if (
fr_timer_in(crl_entry, thread->el->tl, &crl_entry->ev, refresh_delta,
false, crl_refresh_event, crl_entry) <0) {
719 RERROR(
"Failed to set timer to refresh CRL");
722 X509_STORE_CTX_free(verify_ctx);
725 return CALL_RESUME(recv_generic);
730 process_crl_t *
inst = talloc_get_type_abort(mctx->
mi->
data, process_crl_t);
731 process_crl_rctx_t *rctx = talloc_get_type_abort(mctx->
rctx, process_crl_rctx_t);
737 crl_fetching_entry_remove(&
inst->mutable->fetching, rctx->cdp_url);
743 RDEBUG3(
"Sending cached CRL to worker %d", rctx->worker_id);
749 RDEBUG3(
"Sending updated CRL to all workers");
758 process_crl_t *
inst = talloc_get_type_abort(mctx->
mi->
data, process_crl_t);
759 process_thread_crl_t *thread = talloc_get_type_abort(mctx->
thread, process_thread_crl_t);
760 process_crl_rctx_t *rctx = talloc_get_type_abort(mctx->
rctx, process_crl_rctx_t);
764 crl_fetching_entry_remove(&
inst->mutable->fetching, rctx->cdp_url);
771 if (
fr_timer_in(rctx->crl_entry, thread->el->tl, &rctx->crl_entry->ev,
inst->retry_delay,
772 false, crl_refresh_event, rctx->crl_entry) <0) {
773 RERROR(
"Failed to set timer to retry CRL fetch");
811 RDEBUG3(
"Sending fail to worker %d", rctx->worker_id);
819 if (strcmp(fetch->cdp_url, rctx->cdp_url) == 0) {
823 if (fetch->workers[i]) {
825 RDEBUG3(
"Sending fail to worker %d", i);
838 fr_process_state_t
const *state;
843 fr_assert(FR_CRL_PACKET_CODE_VALID(request->packet->code));
845 request->component =
"crl";
846 request->module = NULL;
849 UPDATE_STATE(packet);
852 REDEBUG(
"Invalid packet type (%u)", request->packet->code);
858 return state->recv(p_result, mctx, request);
863 process_crl_t *
inst = talloc_get_type_abort(mctx->
mi->
data, process_crl_t);
865 MEM(
inst->mutable = talloc_zero(NULL, process_crl_mutable_t));
870 inst->verify_store = X509_STORE_new();
871 if (!X509_STORE_load_locations(
inst->verify_store,
inst->ca_file,
inst->ca_path)) {
872 cf_log_err(mctx->
mi->
conf,
"Failed reading Trusted root CA file \"%s\" and path \"%s\"",
877 X509_STORE_set_purpose(
inst->verify_store, X509_PURPOSE_SSL_CLIENT);
884 process_crl_t *
inst = talloc_get_type_abort(mctx->
mi->
data, process_crl_t);
886 if (
inst->verify_store) X509_STORE_free(
inst->verify_store);
894 process_thread_crl_t *t = talloc_get_type_abort(mctx->
thread, process_thread_crl_t);
917 .recv = recv_crl_fetch,
918 .resume = resume_crl_fetch,
919 .section_offset = offsetof(process_crl_sections_t, crl_fetch),
934 .recv = recv_crl_refresh,
935 .resume = resume_crl_fetch,
936 .section_offset = offsetof(process_crl_sections_t, crl_fetch),
948 .send = send_generic,
949 .resume = resume_send_crl_ok,
950 .section_offset = offsetof(process_crl_sections_t, fetch_ok),
962 .send = send_generic,
963 .resume = resume_send_crl_fail,
964 .section_offset = offsetof(process_crl_sections_t, fetch_fail),
982 .send = send_generic,
983 .resume = resume_send_generic,
984 .section_offset = offsetof(process_crl_sections_t, do_not_respond),
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
@ UNLANG_ACTION_FAIL
Encountered an unexpected error.
@ UNLANG_ACTION_CALCULATE_RESULT
Calculate a new section rlm_rcode_t value.
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
#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_IS_SET(_name, _type, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct,...
Defines a CONF_PAIR to C data type mapping.
A section grouping multiple CONF_PAIR.
#define cf_log_err(_cf, _fmt,...)
int fr_coord_to_worker_reply_broadcast(request_t *request)
Send a reply list from a coordinator to all workers.
int fr_coord_to_worker_reply_send(request_t *request, uint32_t worker_id)
Send a reply list from a coordinator to a worker.
fr_coord_pair_t * fr_coord_pair_request_coord_pair(request_t *request)
Return the coord_pair associated with a coord_pair internal request.
int fr_coord_pair_coord_request_start(fr_coord_pair_t *coord_pair, fr_pair_list_t *list, fr_time_t now)
Start a coordinator request to run through a coord_pair process module.
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.
#define fr_dlist_init(_head, _type, _field)
Initialise the head structure of a doubly linked list.
#define fr_dlist_foreach(_list_head, _type, _iter)
Iterate over the contents of a list.
static void * fr_dlist_remove(fr_dlist_head_t *list_head, void *ptr)
Remove an item from the list.
static int fr_dlist_insert_tail(fr_dlist_head_t *list_head, void *ptr)
Insert an item into the tail of a list.
Head of a doubly linked list.
Entry in a doubly linked list.
static fr_dict_t const * dict_freeradius
fr_dict_attr_t const * attr_packet_type
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.
Stores all information relating to an event list.
@ L_DBG_LVL_1
Highest priority debug messages (-x).
main_config_t const * main_config
Main server configuration.
uint32_t max_workers
for the scheduler
@ FR_TYPE_TIME_DELTA
A period of time measured in nanoseconds.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_DATE
Unix time stamp, always has value >2^31.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_INT32
32 Bit signed integer.
@ FR_TYPE_UINT64
64 Bit unsigned integer.
@ FR_TYPE_OCTETS
Raw octets.
unlang_mod_actions_t const mod_actions_authenticate
unlang_mod_action_t actions[RLM_MODULE_NUMCODES]
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 * 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.
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.
int fr_pair_delete_by_da(fr_pair_list_t *list, fr_dict_attr_t const *da)
Delete matching pairs from the specified list.
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
bool fr_pair_immutable(fr_pair_t const *vp)
static unlang_action_t mod_process(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
static const virtual_server_compile_t compile_list[]
static fr_process_state_t const process_state[]
RESUME_FLAG(recv_bfd, UNUSED,)
static int mod_instantiate(module_inst_ctx_t const *mctx)
RECV(for_any_server)
Validate a solicit/rebind/confirm message.
static const conf_parser_t config[]
#define PROCESS_TRACE
Trace each state function as it's entered.
#define PROCESS_CONF_OFFSET(_x)
module_t common
Common fields for all loadable modules.
Common public symbol definition for all process modules.
static fr_schedule_worker_t workers[MAX_WORKERS]
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.
static bool fr_rb_node_inline_in_tree(fr_rb_node_t const *node)
Check to see if an item is in a tree by examining its inline fr_rb_node_t.
#define fr_rb_inline_init(_tree, _type, _field, _data_cmp, _data_free)
Initialises a red black tree.
The main red black tree structure.
#define RLM_MODULE_USER_SECTION_REJECT
Rcodes that translate to a user configurable section failing overall.
#define RETURN_UNLANG_FAIL
@ RLM_MODULE_INVALID
The module considers the request invalid.
@ RLM_MODULE_OK
The module is OK, continue.
@ RLM_MODULE_FAIL
Module failed, don't reply.
@ RLM_MODULE_DISALLOW
Reject the request (user is locked out).
@ RLM_MODULE_REJECT
Immediately reject the request.
@ RLM_MODULE_TIMEOUT
Module (or section) timed out.
@ RLM_MODULE_NOTFOUND
User not found.
@ RLM_MODULE_UPDATED
OK (pairs modified).
@ RLM_MODULE_NOOP
Module succeeded without doing anything.
@ RLM_MODULE_HANDLED
The module handled the request, so stop.
static int mod_detach(module_detach_ctx_t const *mctx)
static int mod_thread_instantiate(module_thread_inst_ctx_t const *mctx)
static fr_dict_attr_t const * attr_delta_crl
fr_value_box_list_t delta_urls
URLs from which a delta CRL can be retrieved.
static fr_dict_attr_t const * attr_base_crl
fr_rb_node_t node
The node in the tree.
char const * cdp_url
The URL of the CRL.
static fr_dict_attr_t const * attr_crl_cdp_url
static fr_dict_t const * dict_crl
static fr_dict_attr_t const * attr_crl_data
A single CRL in the thread specific list of CRLs.
static _Thread_local int worker_id
Internal ID of the current worker thread.
#define SECTION_NAME(_name1, _name2)
Define a section name consisting of a verb and a noun.
#define MODULE_THREAD_INST(_ctype)
CONF_SECTION * conf
Module's instance configuration.
void * data
Module's instance data.
#define MODULE_RCTX(_ctype)
#define MODULE_INST(_ctype)
conf_parser_t const * config
How to convert a CONF_SECTION to a module instance.
#define pair_update_reply(_attr, _da)
Return or allocate a fr_pair_t in the reply list.
eap_aka_sim_process_conf_t * inst
fr_aka_sim_id_type_t type
Stores an attribute, a value and various bits of other data.
char * talloc_bstrdup(TALLOC_CTX *ctx, char const *in)
Binary safe strdup function.
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.
#define talloc_get_type_abort_const
#define talloc_strdup(_ctx, _str)
static const char * names[8]
static int8_t fr_time_delta_cmp(fr_time_delta_t a, fr_time_delta_t b)
Compare two fr_time_delta_t values.
#define fr_time_delta_isneg(_a)
static fr_unix_time_t fr_unix_time_from_sec(int64_t sec)
static fr_time_t fr_time_from_sec(time_t when)
Convert a time_t (wallclock time) to a fr_time_t (internal time)
#define fr_time_gt(_a, _b)
static fr_time_delta_t fr_time_delta_sub(fr_time_delta_t a, fr_time_delta_t b)
#define fr_time_sub(_a, _b)
Subtract one time from another.
#define fr_time_lt(_a, _b)
A time delta, a difference in time measured in nanoseconds.
static fr_event_list_t * el
fr_pair_t * fr_pair_remove(fr_pair_list_t *list, fr_pair_t *vp)
Remove fr_pair_t from a list without freeing.
void fr_pair_list_free(fr_pair_list_t *list)
Free memory used by a valuepair list.
#define fr_pair_list_append_by_da(_ctx, _vp, _list, _attr, _val, _tainted)
Append a pair to a list, assigning its value.
static void fr_pair_set_immutable(fr_pair_t *vp)
int fr_tls_utils_asn1time_to_epoch(time_t *out, ASN1_TIME const *asn1)
Convert OpenSSL's ASN1_TIME to an epoch time.
int fr_value_box_memdup_buffer(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, uint8_t const *src, bool tainted)
Copy a talloced buffer to a fr_value_box_t.
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.
void fr_value_box_clear_value(fr_value_box_t *data)
Clear/free any existing value.
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.
int fr_value_box_bstrndup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, size_t len, bool tainted)
Copy a string to to a fr_value_box_t.
#define fr_box_time_delta(_val)
#define fr_value_box_alloc_null(_ctx)
Allocate a value box for later use with a value assignment function.
#define fr_box_time(_val)
#define fr_value_box_list_foreach(_list_head, _iter)
section_name_t const * section
Identifier for the section.
#define COMPILE_TERMINATOR
Processing sections which are allowed in this virtual server.