The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
rlm_chap.c
Go to the documentation of this file.
1 /*
2  * This program is is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or (at
5  * your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15  */
16 
17 /**
18  * $Id: 166437cc2a7a80ad030c9f66f449b939ebca6f0d $
19  * @file rlm_chap.c
20  * @brief Process chap authentication requests.
21  *
22  * @copyright 2001,2006 The FreeRADIUS server project
23  */
24 RCSID("$Id: 166437cc2a7a80ad030c9f66f449b939ebca6f0d $")
25 
26 #define LOG_PREFIX mctx->inst->name
27 
28 #include <freeradius-devel/server/base.h>
29 #include <freeradius-devel/server/password.h>
30 #include <freeradius-devel/server/module_rlm.h>
31 #include <freeradius-devel/server/cf_parse.h>
32 #include <freeradius-devel/util/chap.h>
33 #include <freeradius-devel/unlang/xlat_func.h>
34 #include <freeradius-devel/unlang/call_env.h>
35 
36 typedef struct {
39 } rlm_chap_t;
40 
41 static const conf_parser_t module_config[] = {
42  { FR_CONF_OFFSET_TYPE_FLAGS("min_challenge_len", FR_TYPE_SIZE, 0, rlm_chap_t, min_challenge_len), .dflt = "16" },
44 };
45 
46 typedef struct {
49 
51  FR_CALL_ENV_METHOD_OUT(chap_xlat_call_env_t),
52  .env = (call_env_parser_t[]){
53  { FR_CALL_ENV_OFFSET("chap_challenge", FR_TYPE_OCTETS,
56  chap_challenge), .pair.dflt = "&Chap-Challenge", .pair.dflt_quote = T_BARE_WORD },
58  }
59 };
60 
61 typedef struct {
66 
68  FR_CALL_ENV_METHOD_OUT(chap_autz_call_env_t),
69  .env = (call_env_parser_t[]){
70  { FR_CALL_ENV_OFFSET("chap_password", FR_TYPE_OCTETS,
72  chap_autz_call_env_t, chap_password),
73  .pair.dflt = "&Chap-Password", .pair.dflt_quote = T_BARE_WORD },
74  { FR_CALL_ENV_PARSE_OFFSET("chap_challenge", FR_TYPE_OCTETS,
76  chap_autz_call_env_t, chap_challenge, chap_challenge_tmpl),
77  .pair.dflt = "&Chap-Challenge", .pair.dflt_quote = T_BARE_WORD },
79  }
80 };
81 
82 typedef struct {
87 
89  FR_CALL_ENV_METHOD_OUT(chap_auth_call_env_t),
90  .env = (call_env_parser_t[]){
91  { FR_CALL_ENV_OFFSET("username", FR_TYPE_STRING,
94  .pair.dflt = "&User-Name", .pair.dflt_quote = T_BARE_WORD },
95  { FR_CALL_ENV_OFFSET("chap_password", FR_TYPE_OCTETS,
97  chap_auth_call_env_t, chap_password),
98  .pair.dflt = "&Chap-Password", .pair.dflt_quote = T_BARE_WORD },
99  { FR_CALL_ENV_OFFSET("chap_challenge", FR_TYPE_OCTETS,
101  chap_auth_call_env_t, chap_challenge),
102  .pair.dflt = "&Chap-Challenge", .pair.dflt_quote = T_BARE_WORD },
104  }
105 };
106 
108 
111  { .out = &dict_freeradius, .proto = "freeradius" },
112  { NULL }
113 };
114 
117 
120  { .out = &attr_auth_type, .name = "Auth-Type", .type = FR_TYPE_UINT32, .dict = &dict_freeradius },
121  { .out = &attr_cleartext_password, .name = "Password.Cleartext", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
122 
123  { NULL }
124 };
125 
127  { .required = true, .single = true, .type = FR_TYPE_STRING },
129 };
130 
131 /** Produce a CHAP-Password hash value
132  *
133  * Example:
134 @verbatim
135 %chap.password(<password>) == 0x<id><md5_hash>
136 @endverbatim
137  *
138  * @ingroup xlat_functions
139  */
141  xlat_ctx_t const *xctx,
142  request_t *request, fr_value_box_list_t *in)
143 {
145  uint8_t chap_password[1 + FR_CHAP_CHALLENGE_LENGTH];
146  fr_value_box_t *vb;
147  uint8_t const *challenge;
148  size_t challenge_len;
149  fr_value_box_t *in_head = fr_value_box_list_head(in);
150  chap_xlat_call_env_t *env_data = talloc_get_type_abort(xctx->env_data, chap_xlat_call_env_t);
151 
152  /*
153  * Use Chap-Challenge pair if present,
154  * Request Authenticator otherwise.
155  */
156  if ((env_data->chap_challenge.type == FR_TYPE_OCTETS) &&
157  (env_data->chap_challenge.vb_length >= inst->min_challenge_len)) {
158  challenge = env_data->chap_challenge.vb_octets;
159  challenge_len = env_data->chap_challenge.vb_length;
160  } else {
161  if (env_data->chap_challenge.type == FR_TYPE_OCTETS)
162  RWDEBUG("&request.CHAP-Challenge shorter than minimum length (%ld)", inst->min_challenge_len);
163  challenge = request->packet->vector;
164  challenge_len = RADIUS_AUTH_VECTOR_LENGTH;
165  }
166  fr_chap_encode(chap_password, (uint8_t)(fr_rand() & 0xff), challenge, challenge_len,
167  in_head->vb_strvalue, in_head->vb_length);
168 
169  MEM(vb = fr_value_box_alloc_null(ctx));
170  fr_value_box_memdup(vb, vb, NULL, chap_password, sizeof(chap_password), false);
171  fr_dcursor_append(out, vb);
172 
173  return XLAT_ACTION_DONE;
174 }
175 
176 static unlang_action_t CC_HINT(nonnull) mod_authorize(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
177 {
178  fr_pair_t *vp;
180  chap_autz_call_env_t *env_data = talloc_get_type_abort(mctx->env_data, chap_autz_call_env_t);
181 
182  if (fr_pair_find_by_da(&request->control_pairs, NULL, attr_auth_type) != NULL) {
183  RDEBUG3("Auth-Type is already set. Not setting 'Auth-Type := %s'", mctx->inst->name);
185  }
186 
187  /*
188  * This case means the warnings below won't be printed
189  * unless there's a CHAP-Password in the request.
190  */
191  if (env_data->chap_password.type != FR_TYPE_OCTETS) {
193  }
194 
195  /*
196  * Create the CHAP-Challenge if it wasn't already in the packet.
197  *
198  * This is so that the rest of the code does not need to
199  * understand CHAP.
200  */
201  if (env_data->chap_challenge.type != FR_TYPE_OCTETS) {
202  RDEBUG2("Creating %s from request authenticator", env_data->chap_challenge_tmpl->name);
203 
204  MEM(vp = fr_pair_afrom_da(request->request_ctx, tmpl_attr_tail_da(env_data->chap_challenge_tmpl)));
205  fr_pair_value_memdup(vp, request->packet->vector, sizeof(request->packet->vector), true);
206  fr_pair_append(&request->request_pairs, vp);
207  }
208 
209  if (!inst->auth_type) {
210  WARN("No 'authenticate %s {...}' section or 'Auth-Type = %s' set. Cannot setup CHAP authentication",
211  mctx->inst->name, mctx->inst->name);
213  }
214 
215  if (!module_rlm_section_type_set(request, attr_auth_type, inst->auth_type)) {
217  }
218 
220 }
221 
222 /*
223  * Find the named user in this modules database. Create the set
224  * of attribute-value pairs to check and reply with for this user
225  * from the database. The authentication code only needs to check
226  * the password, the rest is done here.
227  */
228 static unlang_action_t CC_HINT(nonnull) mod_authenticate(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
229 {
231  fr_pair_t *known_good;
232  uint8_t pass_str[1 + FR_CHAP_CHALLENGE_LENGTH];
233  chap_auth_call_env_t *env_data = talloc_get_type_abort(mctx->env_data, chap_auth_call_env_t);
234 
235  int ret;
236 
237  fr_dict_attr_t const *allowed_passwords[] = { attr_cleartext_password };
238  bool ephemeral;
239 
240  uint8_t const *challenge;
241  size_t challenge_len;
242 
243  if (env_data->username.type != FR_TYPE_STRING) {
244  REDEBUG("&User-Name attribute is required for authentication");
246  }
247 
248  if (env_data->chap_password.type != FR_TYPE_OCTETS) {
249  REDEBUG("You set '&control.Auth-Type = CHAP' for a request that "
250  "does not contain a CHAP-Password attribute!");
252  }
253 
254  if (env_data->chap_password.vb_length == 0) {
255  REDEBUG("&request.CHAP-Password is empty");
257  }
258 
259  if (env_data->chap_password.vb_length != FR_CHAP_CHALLENGE_LENGTH + 1) {
260  REDEBUG("&request.CHAP-Password has invalid length");
262  }
263 
264  /*
265  * Retrieve the normalised version of
266  * the known_good password, without
267  * mangling the current password attributes
268  * in the request.
269  */
270  known_good = password_find(&ephemeral, request, request,
271  allowed_passwords, NUM_ELEMENTS(allowed_passwords),
272  false);
273  if (!known_good) {
274  REDEBUG("No \"known good\" password found for user");
276  }
277 
278  /*
279  * Output is id + password hash
280  */
281 
282  /*
283  * Use Chap-Challenge pair if present,
284  * Request Authenticator otherwise.
285  */
286  if ((env_data->chap_challenge.type == FR_TYPE_OCTETS) &&
287  (env_data->chap_challenge.vb_length >= inst->min_challenge_len)) {
288  challenge = env_data->chap_challenge.vb_octets;
289  challenge_len = env_data->chap_challenge.vb_length;
290  } else {
291  if (env_data->chap_challenge.type == FR_TYPE_OCTETS)
292  RWDEBUG("&request.CHAP-Challenge shorter than minimum length (%ld)", inst->min_challenge_len);
293  challenge = request->packet->vector;
294  challenge_len = RADIUS_AUTH_VECTOR_LENGTH;
295  }
296  fr_chap_encode(pass_str, env_data->chap_password.vb_octets[0], challenge, challenge_len,
297  known_good->vp_strvalue, known_good->vp_length);
298 
299  /*
300  * The password_find function already emits
301  * a log message about the password attribute contents
302  * so we don't need to duplicate it here.
303  */
304  if (RDEBUG_ENABLED3) {
305  uint8_t const *p;
306  size_t length;
307 
308  if (env_data->chap_challenge.type == FR_TYPE_OCTETS) {
309  RDEBUG2("Using challenge from &request.CHAP-Challenge");
310  p = env_data->chap_challenge.vb_octets;
311  length = env_data->chap_challenge.vb_length;
312  } else {
313  RDEBUG2("Using challenge from authenticator field");
314  p = request->packet->vector;
315  length = sizeof(request->packet->vector);
316  }
317 
318  RINDENT();
319  RDEBUG3("CHAP challenge : %pH", fr_box_octets(p, length));
320  RDEBUG3("Client sent : %pH", fr_box_octets(env_data->chap_password.vb_octets + 1,
322  RDEBUG3("We calculated : %pH", fr_box_octets(pass_str + 1, FR_CHAP_CHALLENGE_LENGTH));
323  REXDENT();
324  }
325 
326  /*
327  * Skip the id field at the beginning of the
328  * password and chap response.
329  */
330  ret = fr_digest_cmp(pass_str + 1, env_data->chap_password.vb_octets + 1, FR_CHAP_CHALLENGE_LENGTH);
331  if (ephemeral) TALLOC_FREE(known_good);
332  if (ret != 0) {
333  REDEBUG("Password comparison failed: password is incorrect");
334 
336  }
337 
338  RDEBUG2("CHAP user \"%pV\" authenticated successfully", &env_data->username);
339 
341 }
342 
343 /*
344  * Create instance for our module. Allocate space for
345  * instance structure and read configuration parameters
346  */
347 static int mod_instantiate(module_inst_ctx_t const *mctx)
348 {
349  rlm_chap_t *inst = talloc_get_type_abort(mctx->inst->data, rlm_chap_t);
350 
351  inst->auth_type = fr_dict_enum_by_name(attr_auth_type, mctx->inst->name, -1);
352  if (!inst->auth_type) {
353  WARN("Failed to find 'authenticate %s {...}' section. CHAP authentication will likely not work",
354  mctx->inst->name);
355  }
356 
357  return 0;
358 }
359 
360 static int mod_bootstrap(module_inst_ctx_t const *mctx)
361 {
362  xlat_t *xlat;
363 
364  if (unlikely((xlat = xlat_func_register_module(NULL, mctx, "password", xlat_func_chap_password,
365  FR_TYPE_OCTETS)) == NULL)) return -1;
368 
369  return 0;
370 }
371 
372 /*
373  * The module name should be the only globally exported symbol.
374  * That is, everything else should be 'static'.
375  *
376  * If the module needs to temporarily modify it's instantiation
377  * data, the type should be changed to MODULE_TYPE_THREAD_UNSAFE.
378  * The server will then take care of ensuring that the module
379  * is single-threaded.
380  */
381 extern module_rlm_t rlm_chap;
383  .common = {
384  .magic = MODULE_MAGIC_INIT,
385  .name = "chap",
386  .inst_size = sizeof(rlm_chap_t),
387  .bootstrap = mod_bootstrap,
390  },
391  .method_names = (module_method_name_t[]){
392  { .name1 = "recv", .name2 = "access-request", .method = mod_authorize,
393  .method_env = &chap_autz_method_env },
394  { .name1 = "authenticate", .name2 = CF_IDENT_ANY, .method = mod_authenticate,
395  .method_env = &chap_auth_method_env },
397  }
398 };
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition: action.h:35
#define RCSID(id)
Definition: build.h:444
#define unlikely(_x)
Definition: build.h:378
#define NUM_ELEMENTS(_t)
Definition: build.h:335
#define CALL_ENV_TERMINATOR
Definition: call_env.h:212
#define FR_CALL_ENV_PARSE_OFFSET(_name, _cast_type, _flags, _struct, _field, _parse_field)
Specify a call_env_parser_t which writes out runtime results and the result of the parsing phase to t...
Definition: call_env.h:341
call_env_parser_t const * env
Parsing rules for call method env.
Definition: call_env.h:223
@ CALL_ENV_FLAG_CONCAT
If the tmpl produced multiple boxes they should be concatenated.
Definition: call_env.h:74
@ CALL_ENV_FLAG_ATTRIBUTE
Tmpl must contain an attribute reference.
Definition: call_env.h:84
@ CALL_ENV_FLAG_REQUIRED
Associated conf pair or section is required.
Definition: call_env.h:73
@ CALL_ENV_FLAG_NULLABLE
Tmpl expansions are allowed to produce no output.
Definition: call_env.h:78
#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.
Definition: call_env.h:316
Per method call config.
Definition: call_env.h:171
#define CONF_PARSER_TERMINATOR
Definition: cf_parse.h:626
#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
Definition: cf_parse.h:241
Defines a CONF_PAIR to C data type mapping.
Definition: cf_parse.h:563
#define CF_IDENT_ANY
Definition: cf_util.h:78
void fr_chap_encode(uint8_t out[static 1+FR_CHAP_CHALLENGE_LENGTH], uint8_t id, uint8_t const *challenge, size_t challenge_len, char const *password, size_t password_len)
Encode a CHAP password.
Definition: chap.c:34
#define FR_CHAP_CHALLENGE_LENGTH
Definition: chap.h:33
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
Definition: dcursor.h:405
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition: dict.h:250
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition: dict.h:263
fr_dict_enum_value_t * fr_dict_enum_by_name(fr_dict_attr_t const *da, char const *name, ssize_t len)
Definition: dict_util.c:2992
static fr_slen_t in
Definition: dict.h:645
Specifies an attribute which must be present for the module to function.
Definition: dict.h:249
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition: dict.h:262
Value of an enumerated attribute.
Definition: dict.h:209
char const *_CONST name
Instance name.
Definition: dl_module.h:163
void *_CONST data
Module instance's parsed configuration.
Definition: dl_module.h:165
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition: dl_module.h:65
static xlat_action_t xlat_func_chap_password(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Produce a CHAP-Password hash value.
Definition: rlm_chap.c:140
#define REXDENT()
Exdent (unindent) R* messages by one level.
Definition: log.h:443
#define RWDEBUG(fmt,...)
Definition: log.h:361
#define RDEBUG_ENABLED3
True if request debug level 1-3 messages are enabled.
Definition: log.h:335
#define RDEBUG3(fmt,...)
Definition: log.h:343
#define RINDENT()
Indent R* messages by one level.
Definition: log.h:430
@ FR_TYPE_STRING
String of printable characters.
Definition: merged_model.c:83
@ FR_TYPE_UINT32
32 Bit unsigned integer.
Definition: merged_model.c:99
@ FR_TYPE_SIZE
Unsigned integer capable of representing any memory address on the local system.
Definition: merged_model.c:115
@ FR_TYPE_OCTETS
Raw octets.
Definition: merged_model.c:84
unsigned char uint8_t
Definition: merged_model.c:30
int fr_digest_cmp(uint8_t const *a, uint8_t const *b, size_t length)
Do a comparison of two authentication digests by comparing the FULL data.
Definition: misc.c:463
void * env_data
Per call environment data.
Definition: module_ctx.h:44
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Definition: module_ctx.h:52
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Definition: module_ctx.h:42
Temporary structure to hold arguments for module calls.
Definition: module_ctx.h:41
Temporary structure to hold arguments for instantiation calls.
Definition: module_ctx.h:51
Specifies a module method identifier.
Definition: module_method.c:36
bool module_rlm_section_type_set(request_t *request, fr_dict_attr_t const *type_da, fr_dict_enum_value_t const *enumv)
Set the next section type if it's not already set.
Definition: module_rlm.c:397
module_t common
Common fields presented by all modules.
Definition: module_rlm.h:37
#define RADIUS_AUTH_VECTOR_LENGTH
Definition: net.h:89
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.
Definition: pair.c:688
fr_pair_t * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute and assign a fr_dict_attr_t.
Definition: pair.c:278
int fr_pair_value_memdup(fr_pair_t *vp, uint8_t const *src, size_t len, bool tainted)
Copy data into an "octets" data type.
Definition: pair.c:2978
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
Definition: pair.c:1340
fr_pair_t * password_find(bool *ephemeral, TALLOC_CTX *ctx, request_t *request, fr_dict_attr_t const *allowed_attrs[], size_t allowed_attrs_len, bool normify)
Find a "known good" password in the control list of a request.
Definition: password.c:963
static const conf_parser_t config[]
Definition: base.c:188
#define REDEBUG(fmt,...)
Definition: radclient.h:52
#define RDEBUG2(fmt,...)
Definition: radclient.h:54
#define WARN(fmt,...)
Definition: radclient.h:47
uint32_t fr_rand(void)
Return a 32-bit random number.
Definition: rand.c:106
#define RETURN_MODULE_REJECT
Definition: rcode.h:55
#define RETURN_MODULE_NOOP
Definition: rcode.h:62
#define RETURN_MODULE_INVALID
Definition: rcode.h:59
#define RETURN_MODULE_OK
Definition: rcode.h:57
rlm_rcode_t
Return codes indicating the result of the module call.
Definition: rcode.h:40
fr_dict_attr_autoload_t rlm_chap_dict_attr[]
Definition: rlm_chap.c:119
static const call_env_method_t chap_autz_method_env
Definition: rlm_chap.c:67
fr_value_box_t chap_password
Definition: rlm_chap.c:84
fr_dict_enum_value_t * auth_type
Definition: rlm_chap.c:37
static fr_dict_t const * dict_freeradius
Definition: rlm_chap.c:107
fr_value_box_t chap_challenge
Definition: rlm_chap.c:85
size_t min_challenge_len
Definition: rlm_chap.c:38
static unlang_action_t mod_authenticate(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Definition: rlm_chap.c:228
static int mod_bootstrap(module_inst_ctx_t const *mctx)
Definition: rlm_chap.c:360
fr_value_box_t chap_password
Definition: rlm_chap.c:62
fr_dict_autoload_t rlm_chap_dict[]
Definition: rlm_chap.c:110
static const call_env_method_t chap_auth_method_env
Definition: rlm_chap.c:88
static fr_dict_attr_t const * attr_auth_type
Definition: rlm_chap.c:115
static xlat_arg_parser_t const xlat_func_chap_password_args[]
Definition: rlm_chap.c:126
static fr_dict_attr_t const * attr_cleartext_password
Definition: rlm_chap.c:116
static unlang_action_t mod_authorize(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Definition: rlm_chap.c:176
module_rlm_t rlm_chap
Definition: rlm_chap.c:382
fr_value_box_t chap_challenge
Definition: rlm_chap.c:47
static const call_env_method_t chap_xlat_method_env
Definition: rlm_chap.c:50
tmpl_t * chap_challenge_tmpl
Definition: rlm_chap.c:64
static const conf_parser_t module_config[]
Definition: rlm_chap.c:41
static int mod_instantiate(module_inst_ctx_t const *mctx)
Definition: rlm_chap.c:347
fr_value_box_t username
Definition: rlm_chap.c:83
fr_value_box_t chap_challenge
Definition: rlm_chap.c:63
static int instantiate(module_inst_ctx_t const *mctx)
Definition: rlm_rest.c:1312
username
Definition: rlm_securid.c:420
#define MODULE_NAME_TERMINATOR
Definition: module.h:135
static fr_dict_attr_t const * tmpl_attr_tail_da(tmpl_t const *vpt)
Return the last attribute reference da.
Definition: tmpl.h:796
RETURN_MODULE_FAIL
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
eap_aka_sim_process_conf_t * inst
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition: pair.h:68
#define talloc_get_type_abort_const
Definition: talloc.h:270
@ T_BARE_WORD
Definition: token.h:120
bool required
Argument must be present, and non-empty.
Definition: xlat.h:146
#define XLAT_ARG_PARSER_TERMINATOR
Definition: xlat.h:166
xlat_action_t
Definition: xlat.h:35
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
Definition: xlat.h:41
Definition for a single argument consumend by an xlat function.
Definition: xlat.h:145
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.
Definition: value.c:4417
int nonnull(2, 5))
#define fr_value_box_alloc_null(_ctx)
Allocate a value box for later use with a value assignment function.
Definition: value.h:619
static size_t char ** out
Definition: value.h:984
#define fr_box_octets(_val, _len)
Definition: value.h:281
module_ctx_t const * mctx
Synthesised module calling ctx.
Definition: xlat_ctx.h:45
void * env_data
Expanded call env data.
Definition: xlat_ctx.h:46
An xlat calling ctx.
Definition: xlat_ctx.h:42
int xlat_func_args_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the arguments of an xlat.
Definition: xlat_func.c:360
void xlat_func_call_env_set(xlat_t *x, call_env_method_t const *env_method)
Register call environment of an xlat.
Definition: xlat_func.c:405
xlat_t * xlat_func_register_module(TALLOC_CTX *ctx, module_inst_ctx_t const *mctx, char const *name, xlat_func_t func, fr_type_t return_type)
Register an xlat function for a module.
Definition: xlat_func.c:274