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: e4e7c3348502ce294cf0eb18047e9c3fe4357ee3 $
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: e4e7c3348502ce294cf0eb18047e9c3fe4357ee3 $")
62 
63 #define LOG_PREFIX "eap"
64 
65 #include <freeradius-devel/eap/base.h>
66 #include <freeradius-devel/server/virtual_servers.h>
67 #include <freeradius-devel/server/pair.h>
68 #include <freeradius-devel/server/auth.h>
69 #include <freeradius-devel/unlang/call.h>
70 #include "types.h"
71 #include "attrs.h"
72 
75 
78  { .out = &dict_freeradius, .proto = "freeradius" },
79  { .out = &dict_radius, .proto = "radius" },
80  { NULL }
81 };
82 
87 
98 
101  { .out = &attr_chbind_response_code, .name = "Chbind-Response-Code", .type = FR_TYPE_UINT32, .dict = &dict_freeradius },
102  { .out = &attr_eap_identity, .name = "EAP-Identity", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
103  { .out = &attr_eap_session_id, .name = "EAP-Session-Id", .type = FR_TYPE_OCTETS, .dict = &dict_freeradius },
104  { .out = &attr_eap_type, .name = "EAP-Type", .type = FR_TYPE_UINT32, .dict = &dict_freeradius },
105  { .out = &attr_state, .name = "State", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
106 
107  { .out = &attr_message_authenticator, .name = "Message-Authenticator", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
108  { .out = &attr_eap_channel_binding_message, .name = "Vendor-Specific.UKERNA.EAP-Channel-Binding-Message", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
109  { .out = &attr_eap_message, .name = "EAP-Message", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
110  { .out = &attr_eap_msk, .name = "EAP-MSK", .type = FR_TYPE_OCTETS, .dict = &dict_freeradius },
111  { .out = &attr_eap_emsk, .name = "EAP-EMSK", .type = FR_TYPE_OCTETS, .dict = &dict_freeradius },
112  { .out = &attr_freeradius_proxied_to, .name = "Vendor-Specific.FreeRADIUS.Proxied-To", .type = FR_TYPE_IPV4_ADDR, .dict = &dict_radius },
113  { .out = &attr_ms_mppe_send_key, .name = "Vendor-Specific.Microsoft.MPPE-Send-Key", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
114  { .out = &attr_ms_mppe_recv_key, .name = "Vendor-Specific.Microsoft.MPPE-Recv-Key", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
115  { .out = &attr_user_name, .name = "User-Name", .type = FR_TYPE_STRING, .dict = &dict_radius },
116 
117  { NULL }
118 };
119 
120 void eap_packet_to_vp(TALLOC_CTX *ctx, fr_pair_list_t *list, eap_packet_raw_t const *eap)
121 {
122  int total, size;
123  uint8_t const *ptr;
124  fr_pair_t *vp;
125 
126  total = eap->length[0] * 256 + eap->length[1];
127 
128  if (total == 0) {
129  DEBUG("Asked to encode empty EAP-Message!");
130  return;
131  }
132 
133  ptr = (uint8_t const *) eap;
134 
135  do {
136  size = total;
137  if (size > 253) size = 253;
138 
140  fr_pair_value_memdup(vp, ptr, size, false);
141 
142  fr_pair_append(list, vp);
143 
144  ptr += size;
145  total -= size;
146  } while (total > 0);
147 }
148 
149 /** Basic EAP packet verifications & validations
150  *
151  * @param[in] ctx talloc ctx for the eap packet.
152  * @param[in] eap_packet_p to validate.
153  * @return
154  * - true the packet is valid.
155  * - false the packet is invalid.
156  */
157 static bool eap_is_valid(TALLOC_CTX *ctx, eap_packet_raw_t **eap_packet_p)
158 {
159  uint16_t len;
160  size_t packet_len;
161  eap_packet_raw_t *eap_packet = *eap_packet_p;
162 
163  /*
164  * These length checks are also done by eap_packet_from_vp(),
165  * but that's OK. The static analysis tools aren't smart
166  * enough to figure that out.
167  */
168  packet_len = talloc_array_length((uint8_t *) eap_packet);
169  if (packet_len <= EAP_HEADER_LEN) {
170  fr_strerror_printf("Invalid EAP data length %zd <= 4", packet_len);
171  return false;
172  }
173 
174  memcpy(&len, eap_packet->length, sizeof(uint16_t));
175  len = ntohs(len);
176 
177  if ((len <= EAP_HEADER_LEN) || (len > packet_len)) {
178  fr_strerror_printf("Invalid EAP length field. Expected value in range %u-%zu, was %u bytes",
179  EAP_HEADER_LEN, packet_len, len);
180  return false;
181  }
182 
183  /*
184  * High level EAP packet checks
185  */
186  switch (eap_packet->code) {
188  case FR_EAP_CODE_REQUEST:
189  break;
190 
191  default:
192  fr_strerror_printf("Invalid EAP code %d: Ignoring the packet", eap_packet->code);
193  return false;
194  }
195 
196  if ((eap_packet->data[0] == 0) ||
197  (eap_packet->data[0] >= FR_EAP_METHOD_MAX)) {
198  /*
199  * Handle expanded types by smashing them to
200  * normal types.
201  */
202  if (eap_packet->data[0] == FR_EAP_EXPANDED_TYPE) {
203  uint8_t *p, *q;
204 
205  if (len <= (EAP_HEADER_LEN + 1 + 3 + 4)) {
206  fr_strerror_const("Expanded EAP type is too short: ignoring the packet");
207  return false;
208  }
209 
210  if ((eap_packet->data[1] != 0) ||
211  (eap_packet->data[2] != 0) ||
212  (eap_packet->data[3] != 0)) {
213  fr_strerror_const("Expanded EAP type has unknown Vendor-ID: ignoring the packet");
214  return false;
215  }
216 
217  if ((eap_packet->data[4] != 0) ||
218  (eap_packet->data[5] != 0) ||
219  (eap_packet->data[6] != 0)) {
220  fr_strerror_const("Expanded EAP type has unknown Vendor-Type: ignoring the packet");
221  return false;
222  }
223 
224  if ((eap_packet->data[7] == 0) ||
225  (eap_packet->data[7] >= FR_EAP_METHOD_MAX)) {
226  fr_strerror_printf("Unsupported Expanded EAP type %s (%u): ignoring the packet",
227  eap_type2name(eap_packet->data[7]), eap_packet->data[7]);
228  return false;
229  }
230 
231  if (eap_packet->data[7] == FR_EAP_METHOD_NAK) {
232  fr_strerror_const("Unsupported Expanded EAP-NAK: ignoring the packet");
233  return false;
234  }
235 
236  /*
237  * Re-write the EAP packet to NOT have the expanded type.
238  */
239  q = (uint8_t *) eap_packet;
240  memmove(q + EAP_HEADER_LEN, q + EAP_HEADER_LEN + 7, len - 7 - EAP_HEADER_LEN);
241 
242  p = talloc_realloc(ctx, eap_packet, uint8_t, len - 7);
243  if (!p) {
244  fr_strerror_printf("Unsupported EAP type %s (%u): ignoring the packet",
245  eap_type2name(eap_packet->data[0]), eap_packet->data[0]);
246  return false;
247  }
248 
249  len -= 7;
250  p[2] = (len >> 8) & 0xff;
251  p[3] = len & 0xff;
252 
253  *eap_packet_p = (eap_packet_raw_t *)p;
254 
255  return true;
256  }
257 
258  fr_strerror_printf("Unsupported EAP type %s (%u): ignoring the packet",
259  eap_type2name(eap_packet->data[0]), eap_packet->data[0]);
260  return false;
261  }
262 
263  /* we don't expect notification, but we send it */
264  if (eap_packet->data[0] == FR_EAP_METHOD_NOTIFICATION) {
265  fr_strerror_const("Got NOTIFICATION, Ignoring the packet");
266  return false;
267  }
268 
269  return true;
270 }
271 
272 /*
273  * Handles multiple EAP-Message attrs
274  * ie concatenates all to get the complete EAP packet.
275  *
276  * NOTE: Sometimes Framed-MTU might contain the length of EAP-Message,
277  * refer fragmentation in rfc2869.
278  */
280 {
281  fr_pair_t *vp;
282  eap_packet_raw_t *eap_packet;
283  unsigned char *ptr;
284  uint16_t len;
285  int total_len;
286  fr_dcursor_t cursor;
287 
288  /*
289  * Get only EAP-Message attribute list
290  */
292  if (!vp) {
293  fr_strerror_const("EAP-Message not found");
294  return NULL;
295  }
296 
297  /*
298  * Sanity check the length before doing anything.
299  */
300  if (vp->vp_length < 4) {
301  fr_strerror_const("EAP packet is too short");
302  return NULL;
303  }
304 
305  /*
306  * Get the Actual length from the EAP packet
307  * First EAP-Message contains the EAP packet header
308  */
309  memcpy(&len, vp->vp_strvalue + 2, sizeof(len));
310  len = ntohs(len);
311 
312  /*
313  * Take out even more weird things.
314  */
315  if (len < 4) {
316  fr_strerror_const("EAP packet has invalid length (less than 4 bytes)");
317  return NULL;
318  }
319 
320  /*
321  * Sanity check the length, BEFORE allocating memory.
322  */
323  total_len = 0;
324  for (vp = fr_dcursor_head(&cursor);
325  vp;
326  vp = fr_dcursor_next(&cursor)) {
327  total_len += vp->vp_length;
328 
329  if (total_len > len) {
330  fr_strerror_printf("Malformed EAP packet. Length in packet header %i, "
331  "does not match actual length %i", len, total_len);
332  return NULL;
333  }
334  }
335 
336  /*
337  * If the length is SMALLER, die, too.
338  */
339  if (total_len < len) {
340  fr_strerror_printf("Malformed EAP packet. Length in packet header does not "
341  "match actual length");
342  return NULL;
343  }
344 
345  /*
346  * Now that we know the lengths are OK, allocate memory.
347  */
348  eap_packet = (eap_packet_raw_t *) talloc_zero_array(ctx, uint8_t, len);
349  if (!eap_packet) return NULL;
350 
351  /*
352  * Copy the data from EAP-Message's over to our EAP packet.
353  */
354  ptr = (unsigned char *)eap_packet;
355 
356  /* RADIUS ensures order of attrs, so just concatenate all */
357  for (vp = fr_dcursor_head(&cursor);
358  vp;
359  vp = fr_dcursor_next(&cursor)) {
360  memcpy(ptr, vp->vp_strvalue, vp->vp_length);
361  ptr += vp->vp_length;
362  }
363 
364  if (!eap_is_valid(ctx, &eap_packet)) {
365  talloc_free(eap_packet);
366  return NULL;
367  }
368 
369  return eap_packet;
370 }
371 
372 /*
373  * Add raw hex data to the reply.
374  */
375 void eap_add_reply(request_t *request, fr_dict_attr_t const *da, uint8_t const *value, int len)
376 {
377  fr_pair_t *vp;
378 
379  MEM(pair_update_reply(&vp, da) >= 0);
380  fr_pair_value_memdup(vp, value, len, false);
381 
382  RINDENT();
383  RDEBUG2("&reply.%pP", vp);
384  REXDENT();
385 }
386 
387 /** Run a subrequest through a virtual server, managing the eap_session_t of the child
388  *
389  * If eap_session_t has a child, inject that into the request.
390  *
391  * If after the request has run, the child eap_session_t is no longer present,
392  * we assume it has been freed, and fixup the parent eap_session_t.
393  *
394  * If the eap_session_t pointer changes, this is considered a fatal error.
395  *
396  * @param[in] request the current (real) request.
397  * @param[in] eap_session representing the outer eap method.
398  * @param[in] virtual_server The default virtual server to send the request to.
399  * @return the rcode of the last executed section in the virtual server.
400  */
401 rlm_rcode_t eap_virtual_server(UNUSED request_t *request, UNUSED eap_session_t *eap_session, UNUSED char const *virtual_server)
402 {
403 #if 1
404  return RLM_MODULE_FAIL;
405 #else
406  eap_session_t *eap_session_inner;
407  rlm_rcode_t rcode;
408  fr_pair_t *vp;
409  CONF_SECTION *server_cs;
410 
411  vp = fr_pair_find_by_da(&request->control_pairs, NULL, attr_virtual_server);
412  server_cs = vp ? virtual_server_find(vp->vp_strvalue) : virtual_server_find(virtual_server);
413 
414  if (server_cs) {
415  RDEBUG2("Running request through virtual server \"%s\"", cf_section_name2(unlang_call_current(request)));
416  } else {
417  RDEBUG2("Running request in virtual server");
418  }
419 
420  /*
421  * Add a previously recorded inner eap_session_t back
422  * to the request. This in theory allows infinite
423  * nesting, but this is probably limited somewhere.
424  */
425  if (eap_session->child) {
426  RDEBUG4("Adding eap_session_t %p to child request", eap_session->child);
428  eap_session_t, eap_session->child, false, false, false);
429  }
430 
431  rad_virtual_server(&rcode, request);
432  eap_session_inner = request_data_get(request, NULL, REQUEST_DATA_EAP_SESSION);
433  if (eap_session_inner) {
434  /*
435  * We assume if the inner eap session has changed
436  * then the old one has been freed.
437  */
438  if (!eap_session->child || (eap_session->child != eap_session_inner)) {
439  RDEBUG4("Binding lifetime of child eap_session %p to parent eap_session %p",
440  eap_session_inner, eap_session);
441  talloc_link_ctx(eap_session, eap_session_inner);
442  eap_session->child = eap_session_inner;
443  } else {
444  RDEBUG4("Got eap_session_t %p back unmolested", eap_session->child);
445  }
446  /*
447  * Assume the inner server freed the
448  * eap_session_t and remove our reference to it.
449  *
450  * If it didn't actually free the child (due to error)
451  * the call to talloc_link_ctx (above) ensures it will
452  * be freed when the parent is.
453  */
454  } else if (eap_session->child) {
455  RDEBUG4("Inner server freed eap_session %p", eap_session->child);
456  eap_session->child = NULL;
457  }
458 
459  return rcode;
460 #endif
461 }
462 
463 /** Initialise the lib eap base library
464  *
465  */
466 int eap_base_init(void)
467 {
468  if (fr_dict_autoload(eap_base_dict) < 0) {
469  PERROR("%s", __FUNCTION__);
470  return -1;
471  }
472 
473  /*
474  * But main_config.c does read the dictionaries before
475  * loading modules, so these have to exist.
476  */
478  PERROR("%s", __FUNCTION__);
480  return -1;
481  }
482 
483  return 0;
484 }
485 
486 /** De-init the lib eap base library
487  *
488  */
489 void eap_base_free(void)
490 {
492 }
unlang_action_t rad_virtual_server(rlm_rcode_t *p_result, request_t *request)
Definition: auth.c:48
#define RCSID(id)
Definition: build.h:444
#define UNUSED
Definition: build.h:313
CONF_SECTION * unlang_call_current(request_t *request)
Return the last virtual server that was called.
Definition: call.c:225
A section grouping multiple CONF_PAIR.
Definition: cf_priv.h:89
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
Definition: cf_util.c:1126
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
Definition: dcursor.h:287
static void * fr_dcursor_head(fr_dcursor_t *cursor)
Rewind cursor to the start of the list.
Definition: dcursor.h:233
#define DEBUG(fmt,...)
Definition: dhcpclient.c:39
#define fr_dict_autofree(_to_free)
Definition: dict.h:674
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
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:3647
#define fr_dict_autoload(_to_load)
Definition: dict.h:671
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
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
HIDDEN fr_dict_attr_t const * attr_virtual_server
fr_dict_attr_autoload_t eap_base_dict_attr[]
Definition: base.c:100
void eap_packet_to_vp(TALLOC_CTX *ctx, fr_pair_list_t *list, eap_packet_raw_t const *eap)
Definition: base.c:120
fr_dict_attr_t const * attr_eap_session_id
Definition: base.c:84
fr_dict_attr_t const * attr_state
Definition: base.c:96
fr_dict_attr_t const * attr_eap_identity
Definition: base.c:85
fr_dict_attr_t const * attr_freeradius_proxied_to
Definition: base.c:93
fr_dict_attr_t const * attr_chbind_response_code
Definition: base.c:83
fr_dict_attr_t const * attr_eap_message
Definition: base.c:90
fr_dict_attr_t const * attr_eap_type
Definition: base.c:86
fr_dict_attr_t const * attr_eap_msk
Definition: base.c:91
fr_dict_attr_t const * attr_eap_channel_binding_message
Definition: base.c:89
fr_dict_t const * dict_freeradius
Definition: base.c:73
fr_dict_t const * dict_radius
Definition: base.c:74
int eap_base_init(void)
Initialise the lib eap base library.
Definition: base.c:466
void eap_base_free(void)
De-init the lib eap base library.
Definition: base.c:489
fr_dict_attr_t const * attr_eap_emsk
Definition: base.c:92
fr_dict_attr_t const * attr_ms_mppe_send_key
Definition: base.c:94
fr_dict_attr_t const * attr_user_name
Definition: base.c:97
static bool eap_is_valid(TALLOC_CTX *ctx, eap_packet_raw_t **eap_packet_p)
Basic EAP packet verifications & validations.
Definition: base.c:157
fr_dict_attr_t const * attr_ms_mppe_recv_key
Definition: base.c:95
fr_dict_autoload_t eap_base_dict[]
Definition: base.c:77
rlm_rcode_t eap_virtual_server(UNUSED request_t *request, UNUSED eap_session_t *eap_session, UNUSED char const *virtual_server)
Run a subrequest through a virtual server, managing the eap_session_t of the child.
Definition: base.c:401
void eap_add_reply(request_t *request, fr_dict_attr_t const *da, uint8_t const *value, int len)
Definition: base.c:375
eap_packet_raw_t * eap_packet_from_vp(TALLOC_CTX *ctx, fr_pair_list_t *vps)
Definition: base.c:279
fr_dict_attr_t const * attr_message_authenticator
Definition: base.c:88
#define REQUEST_DATA_EAP_SESSION
Definition: session.h:32
eap_session_t * child
Session for tunneled EAP method.
Definition: session.h:43
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 RDEBUG4(fmt,...)
Definition: log.h:344
#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_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
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
@ RLM_MODULE_FAIL
Module failed, don't reply.
Definition: rcode.h:42
void * request_data_get(request_t *request, void const *unique_ptr, int unique_int)
Get opaque data from a request.
Definition: request_data.c:292
#define request_data_talloc_add(_request, _unique_ptr, _unique_int, _type, _opaque, _free_on_replace, _free_on_parent, _persist)
Add opaque data to a request_t.
Definition: request_data.h:86
#define pair_update_reply(_attr, _da)
Return or allocate a fr_pair_t in the reply list.
Definition: pair.h:129
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
int talloc_link_ctx(TALLOC_CTX *parent, TALLOC_CTX *child)
Link two different parent and child contexts, so the child is freed before the parent.
Definition: talloc.c:167
#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:627
#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.
CONF_SECTION * virtual_server_find(char const *name)
Return virtual server matching the specified name.