28RCSID(
"$Id: ff5d4647dcfeb590999405b439347149b5b0897b $")
30#include <freeradius-devel/server/base.h>
31#include <freeradius-devel/server/module_rlm.h>
32#include <freeradius-devel/tls/base.h>
33#include <freeradius-devel/tls/cert.h>
34#include <freeradius-devel/tls/log.h>
35#include <freeradius-devel/tls/utils.h>
36#include <freeradius-devel/tls/strerror.h>
37#include <freeradius-devel/unlang/xlat_func.h>
39#include <openssl/crypto.h>
40#include <openssl/pem.h>
41#include <openssl/evp.h>
42#include <openssl/rsa.h>
87 {
L(
"DH"), EVP_PKEY_DH },
88 {
L(
"DSA"), EVP_PKEY_DSA },
89 {
L(
"EC"), EVP_PKEY_EC },
90 {
L(
"RSA"), EVP_PKEY_RSA }
98 {
L(
"none"), RSA_NO_PADDING },
99 {
L(
"oaep"), RSA_PKCS1_OAEP_PADDING },
100 {
L(
"pkcs"), RSA_PKCS1_PADDING },
101 {
L(
"x931"), RSA_X931_PADDING }
253 char const *type_str;
256 md = EVP_get_digestbyname(type_str);
258 cf_log_err(ci,
"Invalid digest type \"%s\"", type_str);
262 *((EVP_MD
const **)
out) = md;
282 char const *type_str;
287 cf_log_err(ci,
"Invalid padding type \"%s\"", type_str);
310 char const *type_str;
320 cf_log_err(ci,
"Invalid cipher type \"%s\"", type_str);
371 char const *filename;
378 fp = fopen(filename,
"r");
389 fr_tls_strerror_printf(NULL);
390 cf_log_perr(ci,
"Error loading private certificate file \"%s\"", filename);
395 pkey_type = EVP_PKEY_type(EVP_PKEY_id(pkey));
396 if (pkey_type != EVP_PKEY_RSA) {
397 cf_log_err(ci,
"Expected certificate to contain %s private key, got %s private key",
405 talloc_set_type(pkey, EVP_PKEY);
406 (void)talloc_steal(ctx, pkey);
430 char const *filename;
439 fp = fopen(filename,
"r");
448 cert = PEM_read_X509(fp, NULL, NULL, NULL);
452 fr_tls_strerror_printf(NULL);
453 cf_log_perr(ci,
"Error loading certificate file \"%s\"", filename);
463 talloc_set_type(cert, X509);
464 (void)talloc_steal(ctx, cert);
470 pkey = X509_get_pubkey(cert);
472 fr_tls_strerror_printf(NULL);
473 cf_log_perr(ci,
"Failed extracting public key from certificate");
478 pkey_type = EVP_PKEY_type(EVP_PKEY_id(pkey));
479 if (pkey_type != EVP_PKEY_RSA) {
480 cf_log_err(ci,
"Expected certificate to contain %s public key, got %s public key",
493 cf_log_debug(ci,
"Certificate validity starts at %pV and ends at %pV",
521 talloc_set_type(pkey, EVP_PKEY);
522 (void)talloc_steal(cert, pkey);
526 *(EVP_PKEY **)
out = pkey;
554 char const *plaintext;
555 size_t plaintext_len;
558 size_t ciphertext_len;
563 plaintext = in_head->vb_strvalue;
564 plaintext_len = in_head->vb_length;
569 RHEXDUMP3((
uint8_t const *)plaintext, plaintext_len,
"Plaintext (%zu bytes)", plaintext_len);
571 (
unsigned char const *)plaintext, plaintext_len) <= 0) {
572 fr_tls_log(request,
"Failed getting length of encrypted plaintext");
579 (
unsigned char const *)plaintext, plaintext_len) <= 0) {
580 fr_tls_log(request,
"Failed encrypting plaintext");
584 RHEXDUMP3(ciphertext, ciphertext_len,
"Ciphertext (%zu bytes)", ciphertext_len);
622 unsigned int digest_len = 0;
627 msg = in_head->vb_strvalue;
628 msg_len = in_head->vb_length;
634 fr_tls_log(request,
"Failed initialising message digest");
639 fr_tls_log(request,
"Failed ingesting message");
644 fr_tls_log(request,
"Failed finalising message digest");
653 fr_tls_log(request,
"Failed getting length of digest");
660 fr_tls_log(request,
"Failed signing message digest");
694 size_t ciphertext_len;
697 size_t plaintext_len;
702 ciphertext = in_head->vb_octets;
703 ciphertext_len = in_head->vb_length;
708 RHEXDUMP3(ciphertext, ciphertext_len,
"Ciphertext (%zu bytes)", ciphertext_len);
709 if (EVP_PKEY_decrypt(t->
evp_decrypt_ctx, NULL, &plaintext_len, ciphertext, ciphertext_len) <= 0) {
710 fr_tls_log(request,
"Failed getting length of cleartext");
716 if (EVP_PKEY_decrypt(t->
evp_decrypt_ctx, (
unsigned char *)plaintext, &plaintext_len,
717 ciphertext, ciphertext_len) <= 0) {
718 fr_tls_log(request,
"Failed decrypting ciphertext");
722 RHEXDUMP3((
uint8_t const *)plaintext, plaintext_len,
"Plaintext (%zu bytes)", plaintext_len);
762 unsigned int digest_len = 0;
774 REDEBUG(
"Signature argument wrong type, expected %s, got %s. "
775 "Use %%base64.decode(<text>) or %%hex_decode(<text>) if signature is armoured",
780 sig = in_head->vb_octets;
781 sig_len = in_head->vb_length;
786 args = fr_value_box_list_head(
in);
791 REDEBUG(
"Failed concatenating arguments to form plaintext");
795 msg_len =
args->vb_length;
798 REDEBUG(
"Zero length message data");
806 fr_tls_log(request,
"Failed initialising message digest");
811 fr_tls_log(request,
"Failed ingesting message");
816 fr_tls_log(request,
"Failed finalising message digest");
838 fr_tls_log(request,
"Failed validating signature");
847 { .required =
false, .concat =
false, .single =
true, .type =
FR_TYPE_STRING },
872 if (!fr_value_box_list_next(
in, fr_value_box_list_head(
in))) {
873 REDEBUG(
"Missing digest argument");
880 md_name = ((
fr_value_box_t *)fr_value_box_list_next(
in, fr_value_box_list_head(
in)))->vb_strvalue;
881 md = EVP_get_digestbyname(md_name);
883 REDEBUG(
"Specified digest \"%s\" is not a valid digest type", md_name);
887 md_len = EVP_MD_size(md);
891 if (X509_digest(
inst->rsa->x509_certificate_file, md, digest, (
unsigned int *)&md_len) != 1) {
892 fr_tls_log(request,
"Failed calculating certificate fingerprint");
915 ASN1_INTEGER
const *serial;
918 serial = X509_get0_serialNumber(
inst->rsa->x509_certificate_file);
920 fr_tls_log(request,
"Failed retrieving certificate serial");
937 char const *attribute = fr_value_box_list_head(
in)->vb_strvalue;
942 REDEBUG(
"Unknown certificate attribute \"%s\"", attribute);
953 vb->vb_date =
inst->rsa->not_before;
960 vb->vb_date =
inst->rsa->not_after;
974 EVP_PKEY_CTX_free(evp_pkey_ctx);
986 EVP_MD_CTX_destroy(evp_md_ctx);
993 if (
unlikely(EVP_PKEY_CTX_set_rsa_padding(evp_pkey_ctx, rsa_inst->
padding)) <= 0) {
994 fr_tls_strerror_printf(NULL);
995 PERROR(
"%s: Failed setting RSA padding type", __FUNCTION__);
1000 case RSA_NO_PADDING:
1001 case RSA_X931_PADDING:
1002 case RSA_PKCS1_PADDING:
1008 case RSA_PKCS1_OAEP_PADDING:
1010 fr_tls_strerror_printf(NULL);
1011 PERROR(
"%s: Failed setting OAEP digest", __FUNCTION__);
1016 fr_tls_strerror_printf(NULL);
1017 PERROR(
"%s: Failed setting MGF1 digest", __FUNCTION__);
1033 if (
unlikely(EVP_PKEY_CTX_set0_rsa_oaep_label(evp_pkey_ctx, label, label_len) <= 0)) {
1034 fr_tls_strerror_printf(NULL);
1035 PERROR(
"%s: Failed setting OAEP padding label", __FUNCTION__);
1036 OPENSSL_free(label);
1068 if (
inst->rsa->certificate_file) {
1074 fr_tls_strerror_printf(NULL);
1075 PERROR(
"%s: Failed allocating encrypt EVP_PKEY_CTX", __FUNCTION__);
1086 fr_tls_strerror_printf(NULL);
1087 PERROR(
"%s: Failed initialising encrypt EVP_PKEY_CTX", __FUNCTION__);
1091 ERROR(
"%s: Failed setting padding for encrypt EVP_PKEY_CTX", __FUNCTION__);
1100 fr_tls_strerror_printf(NULL);
1101 PERROR(
"%s: Failed allocating verify EVP_PKEY_CTX", __FUNCTION__);
1112 fr_tls_strerror_printf(NULL);
1113 PERROR(
"%s: Failed initialising verify EVP_PKEY_CTX", __FUNCTION__);
1120 if (
inst->rsa->padding != RSA_PKCS1_OAEP_PADDING) {
1122 ERROR(
"%s: Failed setting padding for verify EVP_PKEY_CTX", __FUNCTION__);
1128 fr_tls_strerror_printf(NULL);
1129 PERROR(
"%s: Failed setting signature digest type", __FUNCTION__);
1134 if (
inst->rsa->private_key_file) {
1140 fr_tls_strerror_printf(NULL);
1141 PERROR(
"%s: Failed allocating decrypt EVP_PKEY_CTX", __FUNCTION__);
1152 fr_tls_strerror_printf(NULL);
1153 PERROR(
"%s: Failed initialising decrypt EVP_PKEY_CTX", __FUNCTION__);
1157 ERROR(
"%s: Failed setting padding for decrypt EVP_PKEY_CTX", __FUNCTION__);
1166 fr_tls_strerror_printf(NULL);
1167 PERROR(
"%s: Failed allocating sign EVP_PKEY_CTX", __FUNCTION__);
1178 fr_tls_strerror_printf(NULL);
1179 PERROR(
"%s: Failed initialising sign EVP_PKEY_CTX", __FUNCTION__);
1186 if (
inst->rsa->padding != RSA_PKCS1_OAEP_PADDING) {
1188 ERROR(
"%s: Failed setting padding for sign EVP_PKEY_CTX", __FUNCTION__);
1194 fr_tls_strerror_printf(NULL);
1195 PERROR(
"%s: Failed setting signature digest type", __FUNCTION__);
1204 fr_tls_strerror_printf(NULL);
1205 PERROR(
"%s: Failed allocating EVP_MD_CTX", __FUNCTION__);
1248 cf_log_err(
conf,
"type = rsa, but no 'rsa { ... }' configuration section provided");
1252 if (!
inst->rsa->private_key_file && !
inst->rsa->certificate_file) {
1254 "'private_key_file' nor 'certificate_file' configured");
1258 if (
inst->rsa->private_key_file) {
1274 if (
inst->rsa->certificate_file) {
1284 if (
inst->rsa->private_key_file &&
inst->rsa->x509_certificate_file) {
1285 if (X509_check_private_key(
inst->rsa->x509_certificate_file,
1286 inst->rsa->private_key_file) == 0) {
1287 fr_tls_strerror_printf(NULL);
1288 cf_log_perr(
conf,
"Private key does not match the certificate public key");
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
#define L(_str)
Helper for initialising arrays of string literals.
int cf_table_parse_int(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Generic function for parsing conf pair values as int.
#define CONF_PARSER_TERMINATOR
cf_parse_t func
Override default parsing behaviour for the specified type with a custom parsing function.
#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
#define FR_CONF_OFFSET_SUBSECTION(_name, _flags, _struct, _field, _subcs)
conf_parser_t which populates a sub-struct using a CONF_SECTION
@ CONF_FLAG_SECRET
Only print value if debug level >= 3.
@ CONF_FLAG_NOT_EMPTY
CONF_PAIR is required to have a non zero length value.
#define FR_CONF_OFFSET_TYPE_FLAGS(_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.
Common header for all CONF_* types.
A section grouping multiple CONF_PAIR.
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
#define cf_log_err(_cf, _fmt,...)
#define cf_log_perr(_cf, _fmt,...)
#define cf_log_pwarn(_cf, _fmt,...)
#define cf_log_debug(_cf, _fmt,...)
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
static xlat_action_t cipher_rsa_decrypt_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Decrypt input data.
static xlat_action_t cipher_rsa_encrypt_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Encrypt input data.
static xlat_action_t cipher_rsa_sign_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Sign input data.
static xlat_action_t cipher_serial_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, UNUSED fr_value_box_list_t *in)
Return the serial of the public certificate.
static xlat_action_t cipher_rsa_verify_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Verify input data.
static xlat_action_t cipher_fingerprint_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Return the fingerprint of the public certificate.
#define RHEXDUMP3(_data, _len, _fmt,...)
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_DATE
Unix time stamp, always has value >2^31.
@ FR_TYPE_BOOL
A truth value.
@ FR_TYPE_OCTETS
Raw octets.
module_instance_t const * mi
Instance of the module being instantiated.
void * thread
Thread specific instance data.
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 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.
EVP_PKEY_CTX * evp_verify_ctx
Pre-allocated evp_pkey_ctx.
static size_t cipher_rsa_padding_len
static int cipher_type_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
Checks if the specified cipher type is valid.
static const conf_parser_t rsa_oaep_config[]
Configuration for the RSA-PCKS1-OAEP padding scheme.
static int cipher_rsa_private_key_file_load(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
cipher_rsa_oaep_t * oaep
OAEP can use a configurable message digest type.
X509 * x509_certificate_file
Needed for extracting certificate attributes.
cipher_cert_verify_mode_t verify_mode
How hard we try to verify the certificate.
static xlat_arg_parser_t const cipher_rsa_verify_xlat_arg[]
static fr_table_num_sorted_t const cipher_rsa_padding[]
The type of padding used.
static fr_table_num_sorted_t const cert_attributes[]
Public key types.
cipher_cert_verify_mode_t
Certificate validation modes.
@ CIPHER_CERT_VERIFY_HARD
Fail if the certificate isn't valid.
@ CIPHER_CERT_VERIFY_SOFT
Warn if the certificate isn't valid.
@ CIPHER_CERT_VERIFY_NONE
Don't check to see if the we're between notBefore or notAfter.
@ CIPHER_CERT_VERIFY_INVALID
static const conf_parser_t rsa_config[]
Configuration for the RSA cipher type.
static int cipher_rsa_padding_params_set(EVP_PKEY_CTX *evp_pkey_ctx, cipher_rsa_t const *rsa_inst)
cipher_type_t type
Type of encryption to use.
static size_t cipher_cert_verify_mode_table_len
@ CIPHER_CERT_ATTR_NOT_AFTER
Time the certificate expires.
@ CIPHER_CERT_ATTR_SERIAL
Certificate's serial number.
@ CIPHER_CERT_ATTR_UNKNOWN
Unrecognised attribute.
@ CIPHER_CERT_ATTR_FINGERPRINT
Dynamically calculated fingerprint.
@ CIPHER_CERT_ATTR_NOT_BEFORE
Time the certificate becomes valid.
char const * label
Additional input to the hashing function.
EVP_MD_CTX * evp_md_ctx
Pre-allocated evp_md_ctx for sign and verify.
int padding
Type of padding to apply to the plaintext or ciphertext before feeding it to RSA crypto functions.
static int mod_bootstrap(module_inst_ctx_t const *mctx)
static int digest_type_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
Calls EVP_get_digestbyname() to convert the digest type.
uint8_t * digest_buff
Pre-allocated digest buffer.
EVP_MD * mgf1_digest
Masking function digest.
static xlat_arg_parser_t const cipher_rsa_decrypt_xlat_arg[]
static fr_table_num_sorted_t const cipher_cert_verify_mode_table[]
@ RLM_CIPHER_TYPE_SYMMETRIC
Any symmetric cipher available via OpenSSL's EVP interface.
@ RLM_CIPHER_TYPE_INVALID
static xlat_arg_parser_t const cipher_rsa_sign_xlat_arg[]
static int _evp_pkey_free(EVP_PKEY *pkey)
Talloc destructor for freeing an EVP_PKEY (representing a certificate)
fr_unix_time_t not_before
Certificate isn't valid before this time.
static xlat_arg_parser_t const cipher_rsa_encrypt_xlat_arg[]
fr_unix_time_t not_after
Certificate isn't valid after this time.
char const * private_key_password
Password to decrypt the private key.
static int cipher_rsa_thread_instantiate(module_thread_inst_ctx_t const *mctx)
Pre-initialises the EVP_PKEY_CTX necessary for performing RSA encryption/decryption/sign/verify.
static int mod_thread_instantiate(module_thread_inst_ctx_t const *mctx)
EVP_PKEY * certificate_file
Public (certificate) file.
EVP_PKEY * private_key_file
Private key file.
static size_t cipher_type_len
static int cipher_rsa_padding_type_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
Checks if the specified padding type is valid.
static int _x509_cert_free(X509 *cert)
Talloc destructor for freeing an X509 struct (representing a public certificate)
static int _evp_md_ctx_free(EVP_MD_CTX *evp_md_ctx)
Talloc destructor for freeing an EVP_MD_CTX.
static xlat_arg_parser_t const cipher_certificate_xlat_args[]
static fr_table_num_sorted_t const cipher_type[]
EVP_PKEY_CTX * evp_decrypt_ctx
Pre-allocated evp_pkey_ctx.
EVP_PKEY_CTX * evp_encrypt_ctx
Pre-allocated evp_pkey_ctx.
static const conf_parser_t module_config[]
static int cipher_rsa_certificate_file_load(TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
static xlat_action_t cipher_certificate_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
static size_t cert_attributes_len
EVP_PKEY_CTX * evp_sign_ctx
Pre-allocated evp_pkey_ctx.
static int _evp_pkey_ctx_free(EVP_PKEY_CTX *evp_pkey_ctx)
Talloc destructor for freeing an EVP_PKEY_CTX.
static size_t pkey_types_len
EVP_MD * sig_digest
Signature digest type.
char const * random_file
If set, we read 10K of data (or the complete file) and use it to seed OpenSSL's PRNG.
static fr_table_num_sorted_t const pkey_types[]
Public key types.
EVP_MD * oaep_digest
Padding digest type.
Configuration for the OAEP padding method.
Configuration for RSA encryption/decryption/signing.
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.
eap_aka_sim_process_conf_t * inst
fr_aka_sim_id_type_t type
eap_type_t type
The preferred EAP-Type of this instance of the EAP-SIM/AKA/AKA' state machine.
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
#define fr_table_value_by_str(_table, _name, _def)
Convert a string to a value using a sorted or ordered table.
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
An element in a lexicographically sorted array of name to num mappings.
char * talloc_bstrndup(TALLOC_CTX *ctx, char const *in, size_t inlen)
Binary safe strndup function.
#define talloc_get_type_abort_const
static size_t talloc_strlen(char const *s)
Returns the length of a talloc array containing a string.
@ XLAT_ARG_VARIADIC_EMPTY_SQUASH
Empty argument groups are removed.
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.
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
int fr_utils_get_private_key_password(char *buf, int size, UNUSED int rwflag, void *u)
Return the static private key password we have configured.
int fr_value_box_mem_alloc(TALLOC_CTX *ctx, uint8_t **out, fr_value_box_t *dst, fr_dict_attr_t const *enumv, size_t len, bool tainted)
Pre-allocate an octets buffer for filling by the caller.
int fr_value_box_mem_realloc(TALLOC_CTX *ctx, uint8_t **out, fr_value_box_t *dst, size_t len)
Change the length of a buffer already allocated to a value box.
int fr_value_box_bstr_alloc(TALLOC_CTX *ctx, char **out, fr_value_box_t *dst, fr_dict_attr_t const *enumv, size_t len, bool tainted)
Alloc and assign an empty \0 terminated string to a fr_value_box_t.
int fr_value_box_bstr_realloc(TALLOC_CTX *ctx, char **out, fr_value_box_t *dst, size_t len)
Change the length of a buffer already allocated to a value box.
int fr_value_box_memdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, uint8_t const *src, size_t len, bool tainted)
Copy a buffer to a fr_value_box_t.
int fr_value_box_list_concat_in_place(TALLOC_CTX *ctx, fr_value_box_t *out, fr_value_box_list_t *list, fr_type_t type, fr_value_box_list_action_t proc_action, bool flatten, size_t max_size)
Concatenate a list of value boxes.
#define fr_value_box_alloc(_ctx, _type, _enumv)
Allocate a value box of a specific type.
#define fr_value_box_alloc_null(_ctx)
Allocate a value box for later use with a value assignment function.
static size_t char ** out
#define fr_box_date(_val)
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.