The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
base.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: cc5a4469cd531055f04d26b3e1998c71fd1bd3a5 $
19  * @file lib/eap/base.c
20  * @brief Code common to clients and to servers.
21  *
22  * @copyright 2000-2003,2006 The FreeRADIUS server project
23  * @copyright 2001 hereUare Communications, Inc. (raghud@hereuare.com)
24  * @copyright 2003 Alan DeKok (aland@freeradius.org)
25  * @copyright 2003 Michael Richardson (mcr@sandelman.ottawa.on.ca)
26  */
27 
28 /*
29  * EAP PACKET FORMAT
30  * --- ------ ------
31  * 0 1 2 3
32  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
33  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
34  * | Code | Identifier | Length |
35  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
36  * | Data ...
37  * +-+-+-+-+
38  *
39  *
40  * EAP Request and Response Packet Format
41  * --- ------- --- -------- ------ ------
42  * 0 1 2 3
43  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
44  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45  * | Code | Identifier | Length |
46  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
47  * | Type | Type-Data ...
48  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
49  *
50  *
51  * EAP Success and Failure Packet Format
52  * --- ------- --- ------- ------ ------
53  * 0 1 2 3
54  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
55  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
56  * | Code | Identifier | Length |
57  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
58  *
59  */
60 
61 RCSID("$Id: cc5a4469cd531055f04d26b3e1998c71fd1bd3a5 $")
62 
63 #define LOG_PREFIX "eap"
64 
65 #include <freeradius-devel/eap/base.h>
66 #include <freeradius-devel/radius/defs.h>
67 #include <freeradius-devel/server/state.h>
68 #include <freeradius-devel/server/virtual_servers.h>
69 #include <freeradius-devel/server/pair.h>
70 #include <freeradius-devel/server/auth.h>
71 #include <freeradius-devel/unlang/call.h>
72 #include <freeradius-devel/unlang/interpret.h>
73 #include <freeradius-devel/unlang/function.h>
74 #include "types.h"
75 #include "attrs.h"
76 
79 
82  { .out = &dict_freeradius, .proto = "freeradius" },
83  { .out = &dict_radius, .proto = "radius" },
84  { NULL }
85 };
86 
103 
106  { .out = &attr_chbind_response_code, .name = "Chbind-Response-Code", .type = FR_TYPE_UINT32, .dict = &dict_freeradius },
107  { .out = &attr_eap_identity, .name = "EAP-Identity", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
108  { .out = &attr_eap_session_id, .name = "EAP-Session-Id", .type = FR_TYPE_OCTETS, .dict = &dict_freeradius },
109  { .out = &attr_eap_type, .name = "EAP-Type", .type = FR_TYPE_UINT32, .dict = &dict_freeradius },
110  { .out = &attr_state, .name = "State", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
111  { .out = &attr_packet_type, .name = "Packet-Type", .type = FR_TYPE_UINT32, .dict = &dict_radius },
112  { .out = &attr_message_authenticator, .name = "Message-Authenticator", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
113  { .out = &attr_eap_channel_binding_message, .name = "Vendor-Specific.UKERNA.EAP-Channel-Binding-Message", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
114  { .out = &attr_eap_message, .name = "EAP-Message", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
115  { .out = &attr_eap_msk, .name = "EAP-MSK", .type = FR_TYPE_OCTETS, .dict = &dict_freeradius },
116  { .out = &attr_eap_emsk, .name = "EAP-EMSK", .type = FR_TYPE_OCTETS, .dict = &dict_freeradius },
117  { .out = &attr_framed_mtu, .name = "Framed-MTU", .type = FR_TYPE_UINT32, .dict = &dict_radius },
118  { .out = &attr_freeradius_proxied_to, .name = "Vendor-Specific.FreeRADIUS.Proxied-To", .type = FR_TYPE_IPV4_ADDR, .dict = &dict_radius },
119  { .out = &attr_ms_mppe_send_key, .name = "Vendor-Specific.Microsoft.MPPE-Send-Key", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
120  { .out = &attr_ms_mppe_recv_key, .name = "Vendor-Specific.Microsoft.MPPE-Recv-Key", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
121  { .out = &attr_user_name, .name = "User-Name", .type = FR_TYPE_STRING, .dict = &dict_radius },
122 
123  { NULL }
124 };
125 
126 void eap_packet_to_vp(TALLOC_CTX *ctx, fr_pair_list_t *list, eap_packet_raw_t const *eap)
127 {
128  int total, size;
129  uint8_t const *ptr;
130  fr_pair_t *vp;
131 
132  total = eap->length[0] * 256 + eap->length[1];
133 
134  if (total == 0) {
135  DEBUG("Asked to encode empty EAP-Message!");
136  return;
137  }
138 
139  ptr = (uint8_t const *) eap;
140 
141  do {
142  size = total;
143  if (size > 253) size = 253;
144 
146  fr_pair_value_memdup(vp, ptr, size, false);
147 
148  fr_pair_append(list, vp);
149 
150  ptr += size;
151  total -= size;
152  } while (total > 0);
153 }
154 
155 /** Basic EAP packet verifications & validations
156  *
157  * @param[in] ctx talloc ctx for the eap packet.
158  * @param[in] eap_packet_p to validate.
159  * @return
160  * - true the packet is valid.
161  * - false the packet is invalid.
162  */
163 static bool eap_is_valid(TALLOC_CTX *ctx, eap_packet_raw_t **eap_packet_p)
164 {
165  uint16_t len;
166  size_t packet_len;
167  eap_packet_raw_t *eap_packet = *eap_packet_p;
168 
169  /*
170  * These length checks are also done by eap_packet_from_vp(),
171  * but that's OK. The static analysis tools aren't smart
172  * enough to figure that out.
173  */
174  packet_len = talloc_array_length((uint8_t *) eap_packet);
175  if (packet_len <= EAP_HEADER_LEN) {
176  fr_strerror_printf("Invalid EAP data length %zd <= 4", packet_len);
177  return false;
178  }
179 
180  memcpy(&len, eap_packet->length, sizeof(uint16_t));
181  len = ntohs(len);
182 
183  if ((len <= EAP_HEADER_LEN) || (len > packet_len)) {
184  fr_strerror_printf("Invalid EAP length field. Expected value in range %u-%zu, was %u bytes",
185  EAP_HEADER_LEN, packet_len, len);
186  return false;
187  }
188 
189  /*
190  * High level EAP packet checks
191  */
192  switch (eap_packet->code) {
194  case FR_EAP_CODE_REQUEST:
195  break;
196 
197  default:
198  fr_strerror_printf("Invalid EAP code %d: Ignoring the packet", eap_packet->code);
199  return false;
200  }
201 
202  if ((eap_packet->data[0] == 0) ||
203  (eap_packet->data[0] >= FR_EAP_METHOD_MAX)) {
204  /*
205  * Handle expanded types by smashing them to
206  * normal types.
207  */
208  if (eap_packet->data[0] == FR_EAP_EXPANDED_TYPE) {
209  uint8_t *p, *q;
210 
211  if (len <= (EAP_HEADER_LEN + 1 + 3 + 4)) {
212  fr_strerror_const("Expanded EAP type is too short: ignoring the packet");
213  return false;
214  }
215 
216  if ((eap_packet->data[1] != 0) ||
217  (eap_packet->data[2] != 0) ||
218  (eap_packet->data[3] != 0)) {
219  fr_strerror_const("Expanded EAP type has unknown Vendor-ID: ignoring the packet");
220  return false;
221  }
222 
223  if ((eap_packet->data[4] != 0) ||
224  (eap_packet->data[5] != 0) ||
225  (eap_packet->data[6] != 0)) {
226  fr_strerror_const("Expanded EAP type has unknown Vendor-Type: ignoring the packet");
227  return false;
228  }
229 
230  if ((eap_packet->data[7] == 0) ||
231  (eap_packet->data[7] >= FR_EAP_METHOD_MAX)) {
232  fr_strerror_printf("Unsupported Expanded EAP type %s (%u): ignoring the packet",
233  eap_type2name(eap_packet->data[7]), eap_packet->data[7]);
234  return false;
235  }
236 
237  if (eap_packet->data[7] == FR_EAP_METHOD_NAK) {
238  fr_strerror_const("Unsupported Expanded EAP-NAK: ignoring the packet");
239  return false;
240  }
241 
242  /*
243  * Re-write the EAP packet to NOT have the expanded type.
244  */
245  q = (uint8_t *) eap_packet;
246  memmove(q + EAP_HEADER_LEN, q + EAP_HEADER_LEN + 7, len - 7 - EAP_HEADER_LEN);
247 
248  p = talloc_realloc(ctx, eap_packet, uint8_t, len - 7);
249  if (!p) {
250  fr_strerror_printf("Unsupported EAP type %s (%u): ignoring the packet",
251  eap_type2name(eap_packet->data[0]), eap_packet->data[0]);
252  return false;
253  }
254 
255  len -= 7;
256  p[2] = (len >> 8) & 0xff;
257  p[3] = len & 0xff;
258 
259  *eap_packet_p = (eap_packet_raw_t *)p;
260 
261  return true;
262  }
263 
264  fr_strerror_printf("Unsupported EAP type %s (%u): ignoring the packet",
265  eap_type2name(eap_packet->data[0]), eap_packet->data[0]);
266  return false;
267  }
268 
269  /* we don't expect notification, but we send it */
270  if (eap_packet->data[0] == FR_EAP_METHOD_NOTIFICATION) {
271  fr_strerror_const("Got NOTIFICATION, Ignoring the packet");
272  return false;
273  }
274 
275  return true;
276 }
277 
278 /*
279  * Handles multiple EAP-Message attrs
280  * ie concatenates all to get the complete EAP packet.
281  *
282  * NOTE: Sometimes Framed-MTU might contain the length of EAP-Message,
283  * refer fragmentation in rfc2869.
284  */
286 {
287  fr_pair_t *vp;
288  eap_packet_raw_t *eap_packet;
289  unsigned char *ptr;
290  uint16_t len;
291  int total_len;
292  fr_dcursor_t cursor;
293 
294  /*
295  * Get only EAP-Message attribute list
296  */
298  if (!vp) {
299  fr_strerror_const("EAP-Message not found");
300  return NULL;
301  }
302 
303  /*
304  * Sanity check the length before doing anything.
305  */
306  if (vp->vp_length < 4) {
307  fr_strerror_const("EAP packet is too short");
308  return NULL;
309  }
310 
311  /*
312  * Get the Actual length from the EAP packet
313  * First EAP-Message contains the EAP packet header
314  */
315  memcpy(&len, vp->vp_strvalue + 2, sizeof(len));
316  len = ntohs(len);
317 
318  /*
319  * Take out even more weird things.
320  */
321  if (len < 4) {
322  fr_strerror_const("EAP packet has invalid length (less than 4 bytes)");
323  return NULL;
324  }
325 
326  /*
327  * Sanity check the length, BEFORE allocating memory.
328  */
329  total_len = 0;
330  for (vp = fr_dcursor_head(&cursor);
331  vp;
332  vp = fr_dcursor_next(&cursor)) {
333  total_len += vp->vp_length;
334 
335  if (total_len > len) {
336  fr_strerror_printf("Malformed EAP packet. Length in packet header %i, "
337  "does not match actual length %i", len, total_len);
338  return NULL;
339  }
340  }
341 
342  /*
343  * If the length is SMALLER, die, too.
344  */
345  if (total_len < len) {
346  fr_strerror_printf("Malformed EAP packet. Length in packet header does not "
347  "match actual length");
348  return NULL;
349  }
350 
351  /*
352  * Now that we know the lengths are OK, allocate memory.
353  */
354  eap_packet = (eap_packet_raw_t *) talloc_zero_array(ctx, uint8_t, len);
355  if (!eap_packet) return NULL;
356 
357  /*
358  * Copy the data from EAP-Message's over to our EAP packet.
359  */
360  ptr = (unsigned char *)eap_packet;
361 
362  /* RADIUS ensures order of attrs, so just concatenate all */
363  for (vp = fr_dcursor_head(&cursor);
364  vp;
365  vp = fr_dcursor_next(&cursor)) {
366  memcpy(ptr, vp->vp_strvalue, vp->vp_length);
367  ptr += vp->vp_length;
368  }
369 
370  if (!eap_is_valid(ctx, &eap_packet)) {
371  talloc_free(eap_packet);
372  return NULL;
373  }
374 
375  return eap_packet;
376 }
377 
378 /*
379  * Add raw hex data to the reply.
380  */
381 void eap_add_reply(request_t *request, fr_dict_attr_t const *da, uint8_t const *value, int len)
382 {
383  fr_pair_t *vp;
384 
385  MEM(pair_update_reply(&vp, da) >= 0);
386  fr_pair_value_memdup(vp, value, len, false);
387 
388  RINDENT();
389  RDEBUG2("&reply.%pP", vp);
390  REXDENT();
391 }
392 
393 /** Handle the result of running a subrequest through a virtual server
394  *
395  * Storing the value of the State attribute in readiness for the next round.
396  */
398  request_t *request, void *uctx)
399 {
400  eap_session_t *eap_session = talloc_get_type_abort(uctx, eap_session_t);
401 
402  /*
403  * Grab the child's session state for re-use in the next round
404  */
406 
408 }
409 
410 /** Run a subrequest through a virtual server
411  *
412  * If eap_session_t has a child_state, inject that as an attribute in the request.
413  *
414  * @param[in] request the current (real) request.
415  * @param[in] eap_session representing the outer eap method.
416  * @param[in] server_cs The virtual server to send the request to.
417  * @return
418  * - UNLANG_ACTION_PUSHED_CHILD on success
419  * - UNLANG_ACTION_FAIL on error
420  */
422 {
423  fr_pair_t *vp;
424 
425  fr_assert(request->parent);
426 
427  RDEBUG2("Running request through virtual server \"%s\"", cf_section_name(server_cs));
428 
429  /*
430  * Re-present the previously stored child's session state if there is one
431  */
433 
434  if (fr_pair_prepend_by_da(request->request_ctx, &vp, &request->request_pairs,
436  vp->vp_uint32 = FR_RADIUS_CODE_ACCESS_REQUEST;
437 
438  if (unlang_function_push(request, NULL, eap_virtual_server_resume, NULL, 0,
439  UNLANG_SUB_FRAME, eap_session) < 0) return UNLANG_ACTION_FAIL;
440 
441  if (unlang_call_push(request, server_cs, UNLANG_SUB_FRAME) < 0) return UNLANG_ACTION_FAIL;
442 
444 }
445 
446 /** Initialise the lib eap base library
447  *
448  */
449 int eap_base_init(void)
450 {
451  if (fr_dict_autoload(eap_base_dict) < 0) {
452  PERROR("%s", __FUNCTION__);
453  return -1;
454  }
455 
456  /*
457  * But main_config.c does read the dictionaries before
458  * loading modules, so these have to exist.
459  */
461  PERROR("%s", __FUNCTION__);
463  return -1;
464  }
465 
466  return 0;
467 }
468 
469 /** De-init the lib eap base library
470  *
471  */
472 void eap_base_free(void)
473 {
475 }
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition: action.h:35
@ UNLANG_ACTION_PUSHED_CHILD
unlang_t pushed a new child onto the stack, execute it instead of continuing.
Definition: action.h:39
@ UNLANG_ACTION_FAIL
Encountered an unexpected error.
Definition: action.h:36
@ UNLANG_ACTION_CALCULATE_RESULT
Calculate a new section rlm_rcode_t value.
Definition: action.h:37
#define RCSID(id)
Definition: build.h:481
#define UNUSED
Definition: build.h:313
unlang_action_t unlang_call_push(request_t *request, CONF_SECTION *server_cs, bool top_frame)
Push a call frame onto the stack.
Definition: call.c:147
A section grouping multiple CONF_PAIR.
Definition: cf_priv.h:101
char const * cf_section_name(CONF_SECTION const *cs)
Return name2 if set, else name1.
Definition: cf_util.c:1197
fr_dcursor_eval_t void const * uctx
Definition: dcursor.h:546
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
Definition: dcursor.h:288
static void * fr_dcursor_head(fr_dcursor_t *cursor)
Rewind cursor to the start of the list.
Definition: dcursor.h:234
@ FR_RADIUS_CODE_ACCESS_REQUEST
RFC2865 - Access-Request.
Definition: defs.h:33
#define DEBUG(fmt,...)
Definition: dhcpclient.c:39
#define fr_dict_autofree(_to_free)
Definition: dict.h:850
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition: dict.h:267
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition: dict.h:280
int fr_dict_attr_autoload(fr_dict_attr_autoload_t const *to_load)
Process a dict_attr_autoload element to load/verify a dictionary attribute.
Definition: dict_util.c:4090
#define fr_dict_autoload(_to_load)
Definition: dict.h:847
Specifies an attribute which must be present for the module to function.
Definition: dict.h:266
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition: dict.h:279
Test enumeration values.
Definition: dict_test.h:92
char const * eap_type2name(eap_type_t method)
Return an EAP-name for a particular type.
Definition: types.c:54
@ FR_EAP_CODE_RESPONSE
Definition: types.h:38
@ FR_EAP_CODE_REQUEST
Definition: types.h:37
#define FR_EAP_EXPANDED_TYPE
Definition: types.h:105
uint8_t data[1]
Definition: types.h:125
uint8_t code
Definition: types.h:122
#define EAP_HEADER_LEN
Definition: types.h:34
uint8_t length[2]
Definition: types.h:124
@ FR_EAP_METHOD_NAK
Definition: types.h:48
@ FR_EAP_METHOD_NOTIFICATION
Definition: types.h:47
@ FR_EAP_METHOD_MAX
Definition: types.h:102
Structure to represent packet format of eap on wire
Definition: types.h:121
#define unlang_function_push(_request, _func, _repeat, _signal, _sigmask, _top_frame, _uctx)
Push a generic function onto the unlang stack.
Definition: function.h:111
#define UNLANG_SUB_FRAME
Definition: interpret.h:36
fr_dict_attr_autoload_t eap_base_dict_attr[]
Definition: base.c:105
fr_dict_attr_t const * attr_packet_type
Definition: base.c:91
void eap_packet_to_vp(TALLOC_CTX *ctx, fr_pair_list_t *list, eap_packet_raw_t const *eap)
Definition: base.c:126
fr_dict_attr_t const * attr_eap_session_id
Definition: base.c:88
fr_dict_attr_t const * attr_state
Definition: base.c:101
fr_dict_attr_t const * attr_eap_identity
Definition: base.c:89
fr_dict_attr_t const * attr_freeradius_proxied_to
Definition: base.c:98
fr_dict_attr_t const * attr_chbind_response_code
Definition: base.c:87
fr_dict_attr_t const * attr_eap_message
Definition: base.c:94
fr_dict_attr_t const * attr_eap_type
Definition: base.c:90
fr_dict_attr_t const * attr_eap_msk
Definition: base.c:95
fr_dict_attr_t const * attr_eap_channel_binding_message
Definition: base.c:93
fr_dict_t const * dict_freeradius
Definition: base.c:77
fr_dict_t const * dict_radius
Definition: base.c:78
int eap_base_init(void)
Initialise the lib eap base library.
Definition: base.c:449
void eap_base_free(void)
De-init the lib eap base library.
Definition: base.c:472
fr_dict_attr_t const * attr_eap_emsk
Definition: base.c:96
fr_dict_attr_t const * attr_ms_mppe_send_key
Definition: base.c:99
static unlang_action_t eap_virtual_server_resume(UNUSED rlm_rcode_t *p_result, UNUSED int *priority, request_t *request, void *uctx)
Handle the result of running a subrequest through a virtual server.
Definition: base.c:397
fr_dict_attr_t const * attr_user_name
Definition: base.c:102
static bool eap_is_valid(TALLOC_CTX *ctx, eap_packet_raw_t **eap_packet_p)
Basic EAP packet verifications & validations.
Definition: base.c:163
fr_dict_attr_t const * attr_framed_mtu
Definition: base.c:97
fr_dict_attr_t const * attr_ms_mppe_recv_key
Definition: base.c:100
unlang_action_t eap_virtual_server(request_t *request, eap_session_t *eap_session, CONF_SECTION *server_cs)
Run a subrequest through a virtual server.
Definition: base.c:421
fr_dict_autoload_t eap_base_dict[]
Definition: base.c:81
void eap_add_reply(request_t *request, fr_dict_attr_t const *da, uint8_t const *value, int len)
Definition: base.c:381
eap_packet_raw_t * eap_packet_from_vp(TALLOC_CTX *ctx, fr_pair_list_t *vps)
Definition: base.c:285
fr_dict_attr_t const * attr_message_authenticator
Definition: base.c:92
char * identity
NAI (User-Name) from EAP-Identity.
Definition: session.h:55
#define REQUEST_DATA_EAP_SESSION
Definition: session.h:32
Tracks the progress of a single session of any EAP method.
Definition: session.h:40
#define PERROR(_fmt,...)
Definition: log.h:228
#define REXDENT()
Exdent (unindent) R* messages by one level.
Definition: log.h:443
#define RINDENT()
Indent R* messages by one level.
Definition: log.h:430
talloc_free(reap)
unsigned short uint16_t
Definition: merged_model.c:31
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
Definition: merged_model.c:86
@ 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_OCTETS
Raw octets.
Definition: merged_model.c:84
unsigned char uint8_t
Definition: merged_model.c:30
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:283
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:2981
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:1345
int fr_pair_prepend_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 prepend)
Definition: pair.c:1493
VQP attributes.
#define RDEBUG2(fmt,...)
Definition: radclient.h:54
rlm_rcode_t
Return codes indicating the result of the module call.
Definition: rcode.h:40
#define pair_update_reply(_attr, _da)
Return or allocate a fr_pair_t in the reply list.
Definition: pair.h:129
void fr_state_restore_to_child(request_t *child, void const *unique_ptr, int unique_int)
Restore subrequest data from a parent request.
Definition: state.c:858
void fr_state_store_in_parent(request_t *child, void const *unique_ptr, int unique_int)
Store subrequest's session-state list and persistable request data in its parent.
Definition: state.c:812
fr_assert(0)
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition: pair.h:68
#define fr_pair_dcursor_by_da_init(_cursor, _list, _da)
Initialise a cursor that will return only attributes matching the specified fr_dict_attr_t.
Definition: pair.h:628
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition: strerror.h:64
#define fr_strerror_const(_msg)
Definition: strerror.h:223
Types of values contained within an fr_value_box_t.