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/tls/strerror.h>
29#include <freeradius-devel/tls/utils.h>
30#include <freeradius-devel/unlang/interpret.h>
31#include <freeradius-devel/util/debug.h>
33#include <openssl/x509.h>
34#include <openssl/x509v3.h>
35#include <openssl/asn1.h>
79} process_crl_sections_t;
84} process_crl_mutable_t;
87 process_crl_sections_t sections;
91 bool force_refresh_is_set;
93 bool force_delta_refresh_is_set;
100 bool allow_not_yet_valid;
102 X509_STORE *verify_store;
104 process_crl_mutable_t *
mutable;
109} process_thread_crl_t;
114 {
FR_CONF_OFFSET(
"early_refresh", process_crl_t, early_refresh) },
115 {
FR_CONF_OFFSET(
"retry_delay", process_crl_t, retry_delay), .dflt =
"30s" },
118 {
FR_CONF_OFFSET(
"allow_expired", process_crl_t, allow_expired) },
119 {
FR_CONF_OFFSET(
"allow_not_yet_valid", process_crl_t, allow_not_yet_valid) },
136 ASN1_INTEGER *crl_num;
140 fr_value_box_list_t delta_urls;
141 char const *base_url;
162} crl_pending_request_t;
166static int8_t crl_cmp(
void const *a,
void const *b)
185#define FR_CRL_PACKET_CODE_VALID(_code) (((_code) > 0) && ((_code) < FR_CRL_CODE_MAX))
186#define FR_CRL_PROCESS_CODE_VALID(_code) (FR_CRL_PACKET_CODE_VALID(_code) || (_code == FR_CRL_DO_NOT_RESPOND))
188#define PROCESS_PACKET_TYPE fr_crl_packet_code_t
189#define PROCESS_CODE_MAX FR_CRL_CODE_MAX
190#define PROCESS_CODE_DO_NOT_RESPOND FR_CRL_DO_NOT_RESPOND
191#define PROCESS_PACKET_CODE_VALID FR_CRL_PROCESS_CODE_VALID
192#define PROCESS_INST process_crl_t
193#define PROCESS_RCTX process_crl_rctx_t
195#include <freeradius-devel/server/process.h>
205 process_crl_t *
inst = talloc_get_type_abort(mctx->
mi->
data, process_crl_t);
213 if (strcmp(fetching->cdp_url,
vp->vp_strvalue) == 0) {
214 if (rctx->worker_id >= 0) fetching->workers[rctx->worker_id] =
true;
215 RDEBUG2(
"CRL already being fetched");
235 MEM(fetch = talloc(
inst->mutable, crl_fetch_t));
236 fetch->cdp_url = rctx->cdp_url;
240 return CALL_RECV(generic);
257 ASN1_INTEGER_get_uint64(&
vp->vp_uint64, crl_entry->crl_num);
260 if (crl_entry->type == CRL_TYPE_BASE) {
272 if (
fr_pair_append_by_da(request->reply_ctx, &
vp, &request->reply_pairs, attr_last_update) < 0)
return -1;
276 if (
fr_pair_append_by_da(request->reply_ctx, &
vp, &request->reply_pairs, attr_next_update) < 0)
return -1;
292 process_crl_t *
inst = talloc_get_type_abort(mctx->
mi->
data, process_crl_t);
293 process_crl_rctx_t *rctx = talloc_get_type_abort(mctx->
rctx, process_crl_rctx_t);
298 rctx->worker_id =
vp->vp_int32;
304 rctx->crl_entry = crl_entry =
fr_rb_find(&
inst->mutable->crls, &find);
316 if (crl_build_reply(request, crl_entry) < 0)
return CALL_SEND_TYPE(
FR_CRL_FETCH_FAIL);
322 return fetch_setup_common(p_result, mctx, request,
vp, rctx);
331 process_crl_t *
inst = talloc_get_type_abort(mctx->
mi->
data, process_crl_t);
332 process_crl_rctx_t *rctx = talloc_get_type_abort(mctx->
rctx, process_crl_rctx_t);
340 if (rctx->crl_entry) rctx->refresh =
true;
342 return fetch_setup_common(p_result, mctx, request,
vp, rctx);
349 if (to_free->crl_num) ASN1_INTEGER_free(to_free->crl_num);
359 if ((to_free->type == CRL_TYPE_BASE) && fr_value_box_list_initialised(&to_free->
delta_urls)) {
363 find.
cdp_url = delta->vb_strvalue;
364 delta_crl =
fr_rb_find(&to_free->inst->mutable->crls, &find);
365 if (!delta_crl)
continue;
382 TALLOC_CTX *local = talloc_new(NULL);
397 if (crl_entry->type == CRL_TYPE_DELTA) {
403 ERROR(
"Failed to initialise CRL refresh request");
404 if (
fr_timer_in(crl_entry, tl, &crl_entry->ev, crl_entry->inst->retry_delay,
false,
405 crl_refresh_event, crl_entry) <0) {
406 ERROR(
"Failed to set timer to retry CRL refresh");
413static inline void crl_fetching_entry_remove(
fr_dlist_head_t *fetching,
char const *cdp_url) {
415 if (strcmp(fetch->cdp_url, cdp_url) == 0) {
425 process_crl_t *
inst = talloc_get_type_abort(mctx->
mi->
data, process_crl_t);
426 process_thread_crl_t *thread = talloc_get_type_abort(mctx->
thread, process_thread_crl_t);
427 process_crl_rctx_t *rctx = talloc_get_type_abort(mctx->
rctx, process_crl_rctx_t);
432 X509_STORE_CTX *verify_ctx = NULL;
435 STACK_OF(DIST_POINT) *dps;
440 switch (RESULT_RCODE) {
442 return CALL_RESUME(recv_generic);
460 data = crl_data->vp_octets;
461 crl = d2i_X509_CRL(NULL, (
const unsigned char **)&
data, crl_data->vp_size);
463 fr_tls_strerror_printf(
"Failed to parse CRL from %s", rctx->cdp_url);
467 verify_ctx = X509_STORE_CTX_new();
468 if (!verify_ctx || !X509_STORE_CTX_init(verify_ctx,
inst->verify_store, NULL, NULL)) {
469 fr_tls_strerror_printf(
"Error initialising X509 store");
471 if (verify_ctx) X509_STORE_CTX_free(verify_ctx);
472 RPERROR(
"Error verifying CRL");
478 xobj = X509_STORE_CTX_get_obj_by_subject(verify_ctx, X509_LU_X509, X509_CRL_get_issuer(crl));
480 fr_tls_strerror_printf(
"CRL issuer certificate not in trusted store");
483 pkey = X509_get_pubkey(X509_OBJECT_get0_X509(xobj));
484 X509_OBJECT_free(xobj);
486 fr_tls_strerror_printf(
"Error getting CRL issuer public key");
489 i = X509_CRL_verify(crl, pkey);
493 fr_tls_strerror_printf(
"Could not verify CRL signature");
497 fr_tls_strerror_printf(
"CRL certificate signature failed");
505 crl_entry->inst =
inst;
510 crl_entry->type = rctx->base_crl ? CRL_TYPE_DELTA : CRL_TYPE_BASE;
511 talloc_set_destructor(crl_entry, _crl_entry_free);
514 RPERROR(
"Failed to parse nextUpdate from CRL");
524 crl_entry->crl_num = X509_CRL_get_ext_d2i(crl, NID_crl_number, &i, NULL);
525 if (!crl_entry->crl_num) {
526 fr_tls_strerror_printf(
"Missing CRL number");
533 if (rctx->crl_entry) {
534 if (ASN1_INTEGER_cmp(crl_entry->crl_num, rctx->crl_entry->crl_num) == 0) {
536 ASN1_INTEGER_get_uint64(&new_num, crl_entry->crl_num);
537 RDEBUG3(
"Refresh returned the same CRL number (%"PRIu64
") as the existing entry", new_num);
540 if (ASN1_INTEGER_cmp(crl_entry->crl_num, rctx->crl_entry->crl_num) < 0) {
541 uint64_t old_num, new_num;
542 ASN1_INTEGER_get_uint64(&old_num, rctx->crl_entry->crl_num);
543 ASN1_INTEGER_get_uint64(&new_num, crl_entry->crl_num);
544 RERROR(
"Got CRL number %"PRIu64
" which is less than current number %"PRIu64,
547 crl_fetching_entry_remove(&
inst->mutable->fetching, rctx->cdp_url);
549 crl_entry = rctx->crl_entry;
560 if (crl_build_reply(request, crl_entry) < 0)
goto error;
570 TALLOC_FREE(rctx->crl_entry);
578 crl_entry->crl_data =
talloc_typed_memdup(crl_entry, crl_data->vp_octets, crl_data->vp_length);
584 if (crl_entry->type == CRL_TYPE_DELTA) {
585 ASN1_INTEGER *base_num = X509_CRL_get_ext_d2i(crl, NID_delta_crl, &i, NULL);
587#ifdef __clang_analyzer__
592 if (
unlikely(!rctx->base_crl))
goto error;
596 RERROR(
"Delta CRL missing Delta CRL Indicator extension");
599 if (ASN1_INTEGER_cmp(base_num, rctx->base_crl->crl_num) > 0) {
600 uint64_t delta_base, crl_num;
601 ASN1_INTEGER_get_uint64(&delta_base, base_num);
602 ASN1_INTEGER_get_uint64(&crl_num, rctx->base_crl->crl_num);
603 RERROR(
"Delta CRL referrs to base CRL number %"PRIu64
", current base is %"PRIu64,
604 delta_base, crl_num);
605 ASN1_INTEGER_free(base_num);
608 ASN1_INTEGER_free(base_num);
609 if (ASN1_INTEGER_cmp(crl_entry->crl_num, rctx->base_crl->crl_num) < 0) {
610 uint64_t delta_num, crl_num;
611 ASN1_INTEGER_get_uint64(&delta_num, crl_entry->crl_num);
612 ASN1_INTEGER_get_uint64(&crl_num, rctx->base_crl->crl_num);
613 RERROR(
"Delta CRL number %"PRIu64
" is less than base CRL number %"PRIu64, delta_num, crl_num);
616 crl_entry->base_url =
talloc_strdup(crl_entry, rctx->base_crl->cdp_url);
620 RPERROR(
"Failed to parse lastUpdate from CRL");
633 if ((crl_entry->type == CRL_TYPE_BASE) && (dps = X509_CRL_get_ext_d2i(crl, NID_freshest_crl, NULL, NULL))) {
635 STACK_OF(GENERAL_NAME) *
names;
640 fr_value_box_list_init(&crl_entry->
delta_urls);
641 for (i = 0; i < sk_DIST_POINT_num(dps); i++) {
642 dp = sk_DIST_POINT_value(dps, i);
643 names = dp->distpoint->name.fullname;
644 for (j = 0; j < sk_GENERAL_NAME_num(
names); j++) {
646 if (
name->type != GEN_URI)
continue;
649 (
char const *)ASN1_STRING_get0_data(
name->d.uniformResourceIdentifier),
650 ASN1_STRING_length(
name->d.uniformResourceIdentifier),
true);
651 RDEBUG3(
"CRL references delta URI %pV", vb);
652 fr_value_box_list_insert_tail(&crl_entry->
delta_urls, vb);
655 CRL_DIST_POINTS_free(dps);
662 if (fr_value_box_list_num_elements(&crl_entry->
delta_urls) > 0) {
665 TALLOC_CTX *local = talloc_new(NULL);
669 if (!
vp)
goto free_local;
678 false) < 0))
goto free_local;
681 RERROR(
"Failed to start fetch of delta CRL");
690 RERROR(
"Failed storing CRL");
694 if (crl_build_reply(request, crl_entry) < 0)
goto error;
702 if (rctx->base_crl &&
inst->force_delta_refresh_is_set) {
705 if (
inst->force_refresh_is_set &&
717 if (
fr_timer_in(crl_entry, thread->el->tl, &crl_entry->ev, refresh_delta,
false, crl_refresh_event, crl_entry) <0) {
718 RERROR(
"Failed to set timer to refresh CRL");
721 X509_STORE_CTX_free(verify_ctx);
724 return CALL_RESUME(recv_generic);
729 process_crl_t *
inst = talloc_get_type_abort(mctx->
mi->
data, process_crl_t);
730 process_crl_rctx_t *rctx = talloc_get_type_abort(mctx->
rctx, process_crl_rctx_t);
736 crl_fetching_entry_remove(&
inst->mutable->fetching, rctx->cdp_url);
742 RDEBUG3(
"Sending cached CRL to worker %d", rctx->worker_id);
748 RDEBUG3(
"Sending updated CRL to all workers");
757 process_crl_t *
inst = talloc_get_type_abort(mctx->
mi->
data, process_crl_t);
758 process_thread_crl_t *thread = talloc_get_type_abort(mctx->
thread, process_thread_crl_t);
759 process_crl_rctx_t *rctx = talloc_get_type_abort(mctx->
rctx, process_crl_rctx_t);
763 crl_fetching_entry_remove(&
inst->mutable->fetching, rctx->cdp_url);
770 if (
fr_timer_in(rctx->crl_entry, thread->el->tl, &rctx->crl_entry->ev,
inst->retry_delay,
771 false, crl_refresh_event, rctx->crl_entry) <0) {
772 RERROR(
"Failed to set timer to retry CRL fetch");
810 RDEBUG3(
"Sending fail to worker %d", rctx->worker_id);
818 if (strcmp(fetch->cdp_url, rctx->cdp_url) == 0) {
822 if (fetch->workers[i]) {
824 RDEBUG3(
"Sending fail to worker %d", i);
837 fr_process_state_t
const *state;
842 fr_assert(FR_CRL_PACKET_CODE_VALID(request->packet->code));
844 request->component =
"crl";
845 request->module = NULL;
848 UPDATE_STATE(packet);
851 REDEBUG(
"Invalid packet type (%u)", request->packet->code);
857 return state->recv(p_result, mctx, request);
862 process_crl_t *
inst = talloc_get_type_abort(mctx->
mi->
data, process_crl_t);
864 MEM(
inst->mutable = talloc_zero(NULL, process_crl_mutable_t));
869 inst->verify_store = X509_STORE_new();
870 if (!X509_STORE_load_locations(
inst->verify_store,
inst->ca_file,
inst->ca_path)) {
871 cf_log_err(mctx->
mi->
conf,
"Failed reading Trusted root CA file \"%s\" and path \"%s\"",
876 X509_STORE_set_purpose(
inst->verify_store, X509_PURPOSE_SSL_CLIENT);
883 process_crl_t *
inst = talloc_get_type_abort(mctx->
mi->
data, process_crl_t);
885 if (
inst->verify_store) X509_STORE_free(
inst->verify_store);
893 process_thread_crl_t *t = talloc_get_type_abort(mctx->
thread, process_thread_crl_t);
916 .recv = recv_crl_fetch,
917 .resume = resume_crl_fetch,
918 .section_offset = offsetof(process_crl_sections_t, crl_fetch),
933 .recv = recv_crl_refresh,
934 .resume = resume_crl_fetch,
935 .section_offset = offsetof(process_crl_sections_t, crl_fetch),
947 .send = send_generic,
948 .resume = resume_send_crl_ok,
949 .section_offset = offsetof(process_crl_sections_t, fetch_ok),
961 .send = send_generic,
962 .resume = resume_send_crl_fail,
963 .section_offset = offsetof(process_crl_sections_t, fetch_fail),
981 .send = send_generic,
982 .resume = resume_send_generic,
983 .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,)
RECV(for_any_server)
Validate a solicit/rebind/confirm message.
static int mod_instantiate(module_inst_ctx_t const *mctx)
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.