The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
peap.c
Go to the documentation of this file.
1 /*
2  * peap.c contains the interfaces that are called from eap
3  *
4  * Version: $Id: e5f6ed03242fd2239a4e62d98e7226757f98b3c3 $
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * @copyright 2003 Alan DeKok (aland@freeradius.org)
21  * @copyright 2006 The FreeRADIUS server project
22  */
23 
24 RCSID("$Id: e5f6ed03242fd2239a4e62d98e7226757f98b3c3 $")
25 USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */
26 
27 #include <freeradius-devel/radius/radius.h>
28 #include <freeradius-devel/radius/defs.h>
29 
30 #include "eap_peap.h"
31 
32 /*
33  * Send protected EAP-Failure
34  *
35  * Result-TLV = Failure
36  */
37 static int eap_peap_failure(request_t *request, eap_session_t *eap_session, fr_tls_session_t *tls_session)
38 {
39  uint8_t tlv_packet[11];
40 
41  RDEBUG2("FAILURE");
42 
43  tlv_packet[0] = FR_EAP_CODE_REQUEST;
44  tlv_packet[1] = eap_session->this_round->response->id +1;
45  tlv_packet[2] = 0;
46  tlv_packet[3] = 11; /* length of this packet */
47  tlv_packet[4] = FR_PEAP_EXTENSIONS_TYPE;
48  tlv_packet[5] = 0x80;
49  tlv_packet[6] = EAP_TLV_ACK_RESULT;
50  tlv_packet[7] = 0;
51  tlv_packet[8] = 2; /* length of the data portion */
52  tlv_packet[9] = 0;
53  tlv_packet[10] = EAP_TLV_FAILURE;
54 
55  (tls_session->record_from_buff)(&tls_session->clean_in, tlv_packet, 11);
56 
57  /*
58  * FIXME: Check the return code.
59  */
60  fr_tls_session_send(request, tls_session);
61 
62  return 1;
63 }
64 
65 
66 /*
67  * Send protected EAP-Success
68  *
69  * Result-TLV = Success
70  */
71 static int eap_peap_success(request_t *request, eap_session_t *eap_session, fr_tls_session_t *tls_session)
72 {
73  uint8_t tlv_packet[11];
74 
75  RDEBUG2("SUCCESS");
76 
77  tlv_packet[0] = FR_EAP_CODE_REQUEST;
78  tlv_packet[1] = eap_session->this_round->response->id +1;
79  tlv_packet[2] = 0;
80  tlv_packet[3] = 11; /* length of this packet */
81  tlv_packet[4] = FR_PEAP_EXTENSIONS_TYPE;
82  tlv_packet[5] = 0x80; /* mandatory AVP */
83  tlv_packet[6] = EAP_TLV_ACK_RESULT;
84  tlv_packet[7] = 0;
85  tlv_packet[8] = 2; /* length of the data portion */
86  tlv_packet[9] = 0;
87  tlv_packet[10] = EAP_TLV_SUCCESS;
88 
89  (tls_session->record_from_buff)(&tls_session->clean_in, tlv_packet, 11);
90 
91  /*
92  * FIXME: Check the return code.
93  */
94  fr_tls_session_send(request, tls_session);
95 
96  return 1;
97 }
98 
99 
100 static int eap_peap_identity(request_t *request, eap_session_t *eap_session, fr_tls_session_t *tls_session)
101 {
102  eap_packet_raw_t eap_packet;
103 
104  eap_packet.code = FR_EAP_CODE_REQUEST;
105  eap_packet.id = eap_session->this_round->response->id + 1;
106  eap_packet.length[0] = 0;
107  eap_packet.length[1] = EAP_HEADER_LEN + 1;
108  eap_packet.data[0] = FR_EAP_METHOD_IDENTITY;
109 
110  (tls_session->record_from_buff)(&tls_session->clean_in, &eap_packet, sizeof(eap_packet));
111  fr_tls_session_send(request, tls_session);
112  (tls_session->record_init)(&tls_session->clean_in);
113 
114  return 1;
115 }
116 
117 /*
118  * Verify the tunneled EAP message.
119  */
120 static int eap_peap_verify(request_t *request, peap_tunnel_t *peap_tunnel,
121  uint8_t const *data, size_t data_len)
122 {
123  eap_packet_raw_t const *eap_packet = (eap_packet_raw_t const *) data;
124  eap_type_t eap_method;
125 
126  /*
127  * No data, OR only 1 byte of EAP type.
128  */
129  if (!data || (data_len == 0) || ((data_len <= 1) && (data[0] != FR_EAP_METHOD_IDENTITY))) return 0;
130 
131  /*
132  * Since the full EAP header is sent for the EAP Extensions type (Type 33),
133  * but not for other Types, it is difficult for the implementation to distinguish
134  * an Extensions Request (Code 1) from an EAP Type 1 (Identity) Request packet.
135  *
136  * i.e. The only way to validate PEAP inner method packets properly is to know
137  * we just send a protected success/failure.
138  */
139  switch (peap_tunnel->status) {
142  if (eap_packet->data[0] != FR_PEAP_EXTENSIONS_TYPE) {
143  REDEBUG("Invalid inner tunnel data, expected method (%u), got (%u)",
144  FR_PEAP_EXTENSIONS_TYPE, eap_packet->data[0]);
145  return -1;
146  }
147  return 0;
148 
149  default:
150  break;
151  }
152 
153  eap_method = data[0]; /* Inner EAP header misses off code and identifier */
154  switch (eap_method) {
156  RDEBUG2("Received EAP-Identity-Response");
157  return 0;
158 
159  /*
160  * We normally do Microsoft MS-CHAPv2 (26), versus
161  * Cisco MS-CHAPv2 (29).
162  */
164  default:
165  RDEBUG2("EAP method %s (%d)", eap_type2name(eap_method), eap_method);
166  return 0;
167  }
168 
169 }
170 
171 /*
172  * Convert a pseudo-EAP packet to a list of fr_pair_t's.
173  */
174 static void eap_peap_inner_to_pairs(TALLOC_CTX *ctx, fr_pair_list_t *pairs,
175  eap_round_t *eap_round,
176  uint8_t const *data, size_t data_len)
177 {
178  size_t total;
179  uint8_t *p;
180  fr_pair_t *vp = NULL;
181 
182  if (data_len > 65535) return; /* paranoia */
183 
185  total = data_len;
186  if (total > 249) total = 249;
187 
188  /*
189  * Hand-build an EAP packet from the crap in PEAP version 0.
190  */
191  MEM(fr_pair_value_mem_alloc(vp, &p, EAP_HEADER_LEN + total, false) == 0);
192  p[0] = FR_EAP_CODE_RESPONSE;
193  p[1] = eap_round->response->id;
194  p[2] = (data_len + EAP_HEADER_LEN) >> 8;
195  p[3] = (data_len + EAP_HEADER_LEN) & 0xff;
196  memcpy(p + EAP_HEADER_LEN, data, total);
197 
198  fr_pair_append(pairs, vp);
199  while (total < data_len) {
201  fr_pair_value_memdup(vp, data + total, (data_len - total), false);
202 
203  total += vp->vp_length;
204 
205  fr_pair_append(pairs, vp);
206  }
207 }
208 
209 
210 /*
211  * Convert a list of fr_pair_t's to an EAP packet, through the
212  * simple expedient of dumping the EAP message
213  */
214 static int eap_peap_inner_from_pairs(request_t *request, fr_tls_session_t *tls_session, fr_pair_list_t *vps)
215 {
216  fr_pair_t *this;
217 
219 
220  /*
221  * Send the EAP data in the first attribute, WITHOUT the
222  * header.
223  */
224  this = fr_pair_list_head(vps);
225  (tls_session->record_from_buff)(&tls_session->clean_in, this->vp_octets + EAP_HEADER_LEN,
226  this->vp_length - EAP_HEADER_LEN);
227 
228  /*
229  * Send the rest of the EAP data, but skipping the first VP.
230  */
231  for (this = fr_pair_list_next(vps, this);
232  this;
233  this = fr_pair_list_next(vps, this)) {
234  (tls_session->record_from_buff)(&tls_session->clean_in, this->vp_octets, this->vp_length);
235  }
236 
237  fr_tls_session_send(request, tls_session);
238 
239  return 1;
240 }
241 
242 
243 /*
244  * See if there's a TLV in the response.
245  */
246 static int eap_peap_check_tlv(request_t *request, uint8_t const *data, size_t data_len)
247 {
248  eap_packet_raw_t const *eap_packet = (eap_packet_raw_t const *) data;
249 
250  if (data_len < 11) return 0;
251 
252  /*
253  * Look for success or failure.
254  */
255  if ((eap_packet->code == FR_EAP_CODE_RESPONSE) &&
256  (eap_packet->data[0] == FR_PEAP_EXTENSIONS_TYPE)) {
257  if (data[10] == EAP_TLV_SUCCESS) {
258  return 1;
259  }
260 
261  if (data[10] == EAP_TLV_FAILURE) {
262  RDEBUG2("Client rejected our response. The password is probably incorrect");
263  return 0;
264  }
265  }
266 
267  RDEBUG2("Unknown TLV %02x", data[10]);
268 
269  return 0;
270 }
271 
272 
273 /*
274  * Use a reply packet to determine what to do.
275  */
276 static unlang_action_t process_reply(rlm_rcode_t *p_result, UNUSED int *priority, request_t *request, void *uctx)
277 {
278  eap_session_t *eap_session = talloc_get_type_abort(uctx, eap_session_t);
279  eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
280  fr_tls_session_t *tls_session = eap_tls_session->tls_session;
281  fr_pair_list_t vps;
282  peap_tunnel_t *t = tls_session->opaque;
283  request_t *parent = request->parent;
284  fr_packet_t *reply = request->reply;
285 
286  if (RDEBUG_ENABLED2) {
287 
288  /*
289  * Note that we don't do *anything* with the reply
290  * attributes.
291  */
292  if (FR_RADIUS_PACKET_CODE_VALID(reply->code)) {
293  RDEBUG2("Got tunneled reply %s", fr_radius_packet_name[reply->code]);
294  } else {
295  RDEBUG2("Got tunneled reply code %i", reply->code);
296  }
297  log_request_pair_list(L_DBG_LVL_2, request, NULL, &request->reply_pairs, NULL);
298  }
299 
300  switch (reply->code) {
302  RDEBUG2("Tunneled authentication was successful");
304  eap_peap_success(request, eap_session, tls_session);
306 
308  RDEBUG2("Tunneled authentication was rejected");
310  eap_peap_failure(request, eap_session, tls_session);
312 
314  RDEBUG2("Got tunneled Access-Challenge");
315 
316  /*
317  * PEAP takes only EAP-Message attributes inside
318  * of the tunnel. Any Reply-Message in the
319  * Access-Challenge is ignored.
320  */
321  fr_pair_list_init(&vps);
322  MEM(fr_pair_list_copy_by_da(t, &vps, &request->reply_pairs, attr_eap_message, 0) >= 0);
323 
324  /*
325  * Handle the ACK, by tunneling any necessary reply
326  * VP's back to the client.
327  */
328  if (!fr_pair_list_empty(&vps)) {
329  eap_peap_inner_from_pairs(parent, tls_session, &vps);
330  fr_pair_list_free(&vps);
331  }
332 
334 
335  default:
336  RDEBUG2("Unknown RADIUS packet type %d: rejecting tunneled user", reply->code);
338  }
339 }
340 
341 
342 static char const *peap_state(peap_tunnel_t *t)
343 {
344  switch (t->status) {
346  return "TUNNEL ESTABLISHED";
347 
349  return "WAITING FOR INNER IDENTITY";
350 
352  return "send tlv success";
353 
355  return "send tlv failure";
356 
358  return "phase2_init";
359 
360  case PEAP_STATUS_PHASE2:
361  return "phase2";
362 
363  default:
364  break;
365  }
366  return "?";
367 }
368 
369 /*
370  * Process the pseudo-EAP contents of the tunneled data.
371  */
373  eap_session_t *eap_session, fr_tls_session_t *tls_session)
374 {
375  peap_tunnel_t *t = tls_session->opaque;
376  request_t *child = NULL;
377  fr_pair_t *vp;
379  uint8_t const *data;
380  size_t data_len;
381  eap_round_t *eap_round = eap_session->this_round;
382 
383  /*
384  * Just look at the buffer directly, without doing
385  * record_to_buff. This lets us avoid another data copy.
386  */
387  data_len = tls_session->clean_out.used;
388  tls_session->clean_out.used = 0;
389  data = tls_session->clean_out.data;
390 
391  RDEBUG2("PEAP state %s", peap_state(t));
392 
393  if ((t->status != PEAP_STATUS_TUNNEL_ESTABLISHED) && (eap_peap_verify(request, t, data, data_len) < 0)) {
394  REDEBUG("Tunneled data is invalid");
396  }
397 
398  switch (t->status) {
400  /* FIXME: should be no data in the buffer here, check & assert? */
401 
402  if (SSL_session_reused(tls_session->ssl)) {
403  RDEBUG2("Skipping Phase2 because of session resumption");
405  /* we're good, send success TLV */
407  eap_peap_success(request, eap_session, tls_session);
408 
409  } else {
410  /* send an identity request */
413  eap_peap_identity(request, eap_session, tls_session);
414  }
415  rcode = RLM_MODULE_HANDLED;
416  goto finish;
417 
419  /* we're expecting an identity response */
420  if (data[0] != FR_EAP_METHOD_IDENTITY) {
421  REDEBUG("Expected EAP-Identity, got something else");
422  rcode = RLM_MODULE_REJECT;
423  goto finish;
424  }
425 
426  /*
427  * Save it for later.
428  */
430  t->username->vp_tainted = true;
431 
432  fr_pair_value_bstrndup(t->username, (char const *)data + 1, data_len - 1, true);
433 
434  RDEBUG2("Got inner identity \"%pV\"", &t->username->data);
436  break;
437 
438  /*
439  * If we authenticated the user, then it's OK.
440  */
442  if (eap_peap_check_tlv(request, data, data_len)) {
443  RDEBUG2("Success");
444  rcode = RLM_MODULE_OK;
445  goto finish;
446  }
447 
448  /*
449  * Otherwise, the client rejected the session
450  * resumption. If the session is being re-used,
451  * we need to do a full authentication.
452  *
453  * We do this by sending an EAP-Identity request
454  * inside of the PEAP tunnel.
455  */
457  RDEBUG2("Client rejected session resumption. Re-starting full authentication");
458 
459  /*
460  * Mark session resumption status.
461  */
464 
465  eap_peap_identity(request, eap_session, tls_session);
466  rcode = RLM_MODULE_HANDLED;
467  goto finish;
468  }
469 
470  REDEBUG("Sent a success, but received something weird in return");
471  rcode = RLM_MODULE_REJECT;
472  goto finish;
473 
474  /*
475  * Supplicant ACKs our failure.
476  */
478  RINDENT();
479  REDEBUG("The users session was previously rejected: returning reject (again.)");
480  RIDEBUG("This means you need to read the PREVIOUS messages in the debug output");
481  RIDEBUG("to find out the reason why the user was rejected");
482  RIDEBUG("Look for \"reject\" or \"fail\". Those earlier messages will tell you");
483  RIDEBUG("what went wrong, and how to fix the problem");
484  REXDENT();
485 
487 
489  RDEBUG2("In state machine in phase2 init?");
490  break;
491 
492  case PEAP_STATUS_PHASE2:
493  break;
494 
495  default:
496  REDEBUG("Unhandled state in peap");
497  rcode = RLM_MODULE_REJECT;
498  goto finish;
499  }
500 
501  MEM(child = unlang_subrequest_alloc(request, request->dict));
502  fr_assert(fr_pair_list_empty(&child->request_pairs));
503 
504  switch (t->status) {
505  /*
506  * If we're in PHASE2_INIT, the phase2 method hasn't been
507  * sent an Identity packet yet; do so from the stored
508  * username and this will kick off the phase2 eap method
509  */
511  {
512  size_t len;
513  uint8_t *q;
514 
515  fr_assert(t->username);
516 
517  len = t->username->vp_length + EAP_HEADER_LEN + 1;
519 
520  MEM(vp = fr_pair_afrom_da(child->request_ctx, attr_eap_message));
521  MEM(fr_pair_value_mem_alloc(vp, &q, len, false) == 0);
522  q[0] = FR_EAP_CODE_RESPONSE;
523  q[1] = eap_round->response->id;
524  q[2] = (len >> 8) & 0xff;
525  q[3] = len & 0xff;
526  q[4] = FR_EAP_METHOD_IDENTITY;
527  memcpy(q + EAP_HEADER_LEN + 1,
528  t->username->vp_strvalue, t->username->vp_length);
529  fr_pair_append(&child->request_pairs, vp);
530  }
531  break;
532 
533  case PEAP_STATUS_PHASE2:
534  eap_peap_inner_to_pairs(child->request_ctx, &child->request_pairs,
535  eap_round, data, data_len);
536  if (fr_pair_list_empty(&child->request_pairs)) {
537  talloc_free(child);
538  RDEBUG2("Unable to convert tunneled EAP packet to internal server data structures");
539  rcode = RLM_MODULE_REJECT;
540  goto finish;
541  }
542  break;
543 
544  default:
545  REDEBUG("Invalid state change in PEAP");
546  rcode = RLM_MODULE_REJECT;
547  goto finish;
548  }
549 
550  RDEBUG2("Got tunneled request");
551  log_request_pair_list(L_DBG_LVL_2, request, NULL, &child->request_pairs, NULL);
552 
553  /*
554  * Update other items in the request_t data structure.
555  */
556  if (!t->username) {
557  /*
558  * There's no User-Name in the tunneled session,
559  * so we add one here, by pulling it out of the
560  * EAP-Identity packet.
561  */
562  if ((data[0] == FR_EAP_METHOD_IDENTITY) && (data_len > 1)) {
564  fr_assert(t->username != NULL);
565  t->username->vp_tainted = true;
566 
567  fr_pair_value_bstrndup(t->username, (char const *)data + 1, data_len - 1, true);
568 
569  RDEBUG2("Got tunneled identity of %pV", &t->username->data);
570  }
571  } /* else there WAS a t->username */
572 
573  if (t->username) {
574  vp = fr_pair_copy(child->request_ctx, t->username);
575  fr_pair_append(&child->request_pairs, vp);
576  RDEBUG2("Setting &request.User-Name from tunneled (inner) identity \"%s\"",
577  vp->vp_strvalue);
578  } else {
579  RDEBUG2("No tunnel username (SSL resumption?)");
580  }
581 
582  if (unlang_subrequest_child_push(&eap_session->submodule_rcode, child,
583  &(unlang_subrequest_session_t){ .enable = true, .unique_ptr = child },
584  false, UNLANG_SUB_FRAME) < 0) goto finish;
585  if (unlang_function_push(child, NULL, process_reply, NULL, 0,
586  UNLANG_SUB_FRAME, eap_session) != UNLANG_ACTION_PUSHED_CHILD) goto finish;
587 
588  /*
589  * Call authentication recursively, which will
590  * do PAP, CHAP, MS-CHAP, etc.
591  */
592  return eap_virtual_server(child, eap_session, t->server_cs);
593 
594 finish:
595  if (child) request_detach(child);
596 
597  RETURN_MODULE_RCODE(rcode);
598 }
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
#define USES_APPLE_DEPRECATED_API
Definition: build.h:468
#define RCSID(id)
Definition: build.h:481
#define UNUSED
Definition: build.h:313
eap_packet_t * response
Packet we received from the peer.
Definition: compose.h:49
uint8_t id
Definition: compose.h:37
Contains a pair of request and response packets.
Definition: compose.h:48
fr_dcursor_eval_t void const * uctx
Definition: dcursor.h:546
@ FR_RADIUS_CODE_ACCESS_CHALLENGE
RFC2865 - Access-Challenge.
Definition: defs.h:43
@ FR_RADIUS_CODE_ACCESS_ACCEPT
RFC2865 - Access-Accept.
Definition: defs.h:34
@ FR_RADIUS_CODE_ACCESS_REJECT
RFC2865 - Access-Reject.
Definition: defs.h:35
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
uint8_t data[1]
Definition: types.h:125
enum eap_type eap_type_t
uint8_t code
Definition: types.h:122
#define EAP_HEADER_LEN
Definition: types.h:34
uint8_t length[2]
Definition: types.h:124
uint8_t id
Definition: types.h:123
@ FR_EAP_METHOD_MSCHAPV2
Definition: types.h:71
@ FR_EAP_METHOD_IDENTITY
Definition: types.h:46
Structure to represent packet format of eap on wire
Definition: types.h:121
#define EAP_TLV_FAILURE
Definition: eap_peap.h:61
@ PEAP_STATUS_PHASE2_INIT
Definition: eap_peap.h:34
@ PEAP_STATUS_TUNNEL_ESTABLISHED
Definition: eap_peap.h:32
@ PEAP_STATUS_PHASE2
Definition: eap_peap.h:35
@ PEAP_STATUS_INNER_IDENTITY_REQ_SENT
Definition: eap_peap.h:33
@ PEAP_STATUS_SENT_TLV_SUCCESS
Definition: eap_peap.h:30
@ PEAP_STATUS_SENT_TLV_FAILURE
Definition: eap_peap.h:31
@ PEAP_RESUMPTION_YES
Definition: eap_peap.h:40
@ PEAP_RESUMPTION_NO
Definition: eap_peap.h:39
#define FR_PEAP_EXTENSIONS_TYPE
Definition: eap_peap.h:64
peap_status status
Definition: eap_peap.h:46
peap_resumption session_resumption_state
Definition: eap_peap.h:50
#define EAP_TLV_SUCCESS
Definition: eap_peap.h:60
CONF_SECTION * server_cs
Definition: eap_peap.h:49
fr_pair_t * username
Definition: eap_peap.h:45
#define EAP_TLV_ACK_RESULT
Definition: eap_peap.h:62
#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
HIDDEN fr_dict_attr_t const * attr_eap_message
Definition: base.c:94
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
void * opaque
Opaque data used by EAP methods.
Definition: session.h:62
rlm_rcode_t submodule_rcode
Result of last submodule call.
Definition: session.h:46
eap_round_t * this_round
The EAP response we're processing, and the EAP request we're building.
Definition: session.h:59
Tracks the progress of a single session of any EAP method.
Definition: session.h:40
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.
Definition: log.c:830
#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)
@ L_DBG_LVL_2
2nd highest priority debug messages (-xx | -X).
Definition: log.h:71
unsigned char uint8_t
Definition: merged_model.c:30
int fr_pair_list_copy_by_da(TALLOC_CTX *ctx, fr_pair_list_t *to, fr_pair_list_t const *from, fr_dict_attr_t const *da, unsigned int count)
Duplicate pairs in a list matching the specified da.
Definition: pair.c:2406
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
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
Definition: pair.c:46
int fr_pair_value_bstrndup(fr_pair_t *vp, char const *src, size_t len, bool tainted)
Copy data into a "string" type value pair.
Definition: pair.c:2784
fr_pair_t * fr_pair_copy(TALLOC_CTX *ctx, fr_pair_t const *vp)
Copy a single valuepair.
Definition: pair.c:489
int fr_pair_value_mem_alloc(fr_pair_t *vp, uint8_t **out, size_t size, bool tainted)
Pre-allocate a memory buffer for a "octets" type value pair.
Definition: pair.c:2930
static USES_APPLE_DEPRECATED_API int eap_peap_failure(request_t *request, eap_session_t *eap_session, fr_tls_session_t *tls_session)
Definition: peap.c:37
static unlang_action_t process_reply(rlm_rcode_t *p_result, UNUSED int *priority, request_t *request, void *uctx)
Definition: peap.c:276
static int eap_peap_success(request_t *request, eap_session_t *eap_session, fr_tls_session_t *tls_session)
Definition: peap.c:71
static int eap_peap_identity(request_t *request, eap_session_t *eap_session, fr_tls_session_t *tls_session)
Definition: peap.c:100
static int eap_peap_check_tlv(request_t *request, uint8_t const *data, size_t data_len)
Definition: peap.c:246
static void eap_peap_inner_to_pairs(TALLOC_CTX *ctx, fr_pair_list_t *pairs, eap_round_t *eap_round, uint8_t const *data, size_t data_len)
Definition: peap.c:174
static int eap_peap_inner_from_pairs(request_t *request, fr_tls_session_t *tls_session, fr_pair_list_t *vps)
Definition: peap.c:214
unlang_action_t eap_peap_process(rlm_rcode_t *p_result, request_t *request, eap_session_t *eap_session, fr_tls_session_t *tls_session)
Definition: peap.c:372
static char const * peap_state(peap_tunnel_t *t)
Definition: peap.c:342
static int eap_peap_verify(request_t *request, peap_tunnel_t *peap_tunnel, uint8_t const *data, size_t data_len)
Definition: peap.c:120
char const * fr_radius_packet_name[FR_RADIUS_CODE_MAX]
Definition: base.c:112
static fr_dict_attr_t const * attr_user_name
Definition: radclient-ng.c:128
#define REDEBUG(fmt,...)
Definition: radclient.h:52
#define RDEBUG_ENABLED2()
Definition: radclient.h:50
#define RDEBUG2(fmt,...)
Definition: radclient.h:54
#define FR_RADIUS_PACKET_CODE_VALID(_x)
Definition: radius.h:52
#define RIDEBUG(fmt,...)
Definition: radsniff.h:65
#define RETURN_MODULE_REJECT
Definition: rcode.h:55
#define RETURN_MODULE_RCODE(_rcode)
Definition: rcode.h:64
#define RETURN_MODULE_HANDLED
Definition: rcode.h:58
rlm_rcode_t
Return codes indicating the result of the module call.
Definition: rcode.h:40
@ RLM_MODULE_OK
The module is OK, continue.
Definition: rcode.h:43
@ RLM_MODULE_REJECT
Immediately reject the request.
Definition: rcode.h:41
@ RLM_MODULE_HANDLED
The module handled the request, so stop.
Definition: rcode.h:44
int request_detach(request_t *child)
Unlink a subrequest from its parent.
Definition: request.c:668
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
request_t * unlang_subrequest_alloc(request_t *parent, fr_dict_t const *namespace)
Allocate a subrequest to run through a virtual server at some point in the future.
Definition: subrequest.c:287
int unlang_subrequest_child_push(rlm_rcode_t *out, request_t *child, unlang_subrequest_session_t const *session, bool free_child, bool top_frame)
Push a pre-existing child back onto the stack as a subrequest.
fr_tls_session_t * tls_session
TLS session used to authenticate peer or tunnel sensitive data.
Definition: tls.h:129
Tracks the state of an EAP-TLS session.
Definition: tls.h:126
unsigned int code
Packet code (type).
Definition: packet.h:61
fr_pair_t * fr_pair_list_head(fr_pair_list_t const *list)
Get the head of a valuepair list.
Definition: pair_inline.c:43
bool fr_pair_list_empty(fr_pair_list_t const *list)
Is a valuepair list empty.
Definition: pair_inline.c:125
fr_pair_t * fr_pair_list_next(fr_pair_list_t const *list, fr_pair_t const *item))
Get the next item in a valuepair list after a specific entry.
Definition: pair_inline.c:70
void fr_pair_list_free(fr_pair_list_t *list)
Free memory used by a valuepair list.
Definition: pair_inline.c:113
static fr_slen_t parent
Definition: pair.h:851
static fr_slen_t data
Definition: value.h:1265