All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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: becfa6c952dc952c4ee1d66619e5d069306c77a3 $
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: becfa6c952dc952c4ee1d66619e5d069306c77a3 $")
25 USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */
26 
27 #include "eap_peap.h"
28 
29 static int setup_fake_request(REQUEST *request, REQUEST *fake, peap_tunnel_t *t);
30 
31 /*
32  * Send protected EAP-Failure
33  *
34  * Result-TLV = Failure
35  */
36 static int eap_peap_failure(eap_session_t *eap_session, tls_session_t *tls_session)
37 {
38  uint8_t tlv_packet[11];
39  REQUEST *request = eap_session->request;
40 
41  RDEBUG2("FAILURE");
42 
43  tlv_packet[0] = PW_EAP_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] = PW_EAP_TLV;
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  tls_handshake_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(eap_session_t *eap_session, tls_session_t *tls_session)
72 {
73  uint8_t tlv_packet[11];
74  REQUEST *request = eap_session->request;
75 
76  RDEBUG2("SUCCESS");
77 
78  tlv_packet[0] = PW_EAP_REQUEST;
79  tlv_packet[1] = eap_session->this_round->response->id +1;
80  tlv_packet[2] = 0;
81  tlv_packet[3] = 11; /* length of this packet */
82  tlv_packet[4] = PW_EAP_TLV;
83  tlv_packet[5] = 0x80; /* mandatory AVP */
84  tlv_packet[6] = EAP_TLV_ACK_RESULT;
85  tlv_packet[7] = 0;
86  tlv_packet[8] = 2; /* length of the data portion */
87  tlv_packet[9] = 0;
88  tlv_packet[10] = EAP_TLV_SUCCESS;
89 
90  (tls_session->record_from_buff)(&tls_session->clean_in, tlv_packet, 11);
91 
92  /*
93  * FIXME: Check the return code.
94  */
95  tls_handshake_send(request, tls_session);
96 
97  return 1;
98 }
99 
100 
101 static int eap_peap_identity(eap_session_t *eap_session, tls_session_t *tls_session)
102 {
104 
105  eap_packet.code = PW_EAP_REQUEST;
106  eap_packet.id = eap_session->this_round->response->id + 1;
107  eap_packet.length[0] = 0;
108  eap_packet.length[1] = EAP_HEADER_LEN + 1;
109  eap_packet.data[0] = PW_EAP_IDENTITY;
110 
111  (tls_session->record_from_buff)(&tls_session->clean_in,
112  &eap_packet, sizeof(eap_packet));
113 
114  tls_handshake_send(eap_session->request, tls_session);
115  (tls_session->record_init)(&tls_session->clean_in);
116 
117  return 1;
118 }
119 
120 /*
121  * Send an MS SoH request
122  */
123 static int eap_peap_soh(eap_session_t *eap_session, tls_session_t *tls_session)
124 {
125  uint8_t tlv_packet[20];
126 
127  tlv_packet[0] = 254; /* extended type */
128 
129  tlv_packet[1] = 0;
130  tlv_packet[2] = 0x01; /* ms vendor */
131  tlv_packet[3] = 0x37;
132 
133  tlv_packet[4] = 0; /* ms soh eap */
134  tlv_packet[5] = 0;
135  tlv_packet[6] = 0;
136  tlv_packet[7] = 0x21;
137 
138  tlv_packet[8] = 0; /* vendor-spec tlv */
139  tlv_packet[9] = 7;
140 
141  tlv_packet[10] = 0;
142  tlv_packet[11] = 8; /* payload len */
143 
144  tlv_packet[12] = 0; /* ms vendor */
145  tlv_packet[13] = 0;
146  tlv_packet[14] = 0x01;
147  tlv_packet[15] = 0x37;
148 
149  tlv_packet[16] = 0;
150  tlv_packet[17] = 2;
151  tlv_packet[18] = 0;
152  tlv_packet[19] = 0;
153 
154  (tls_session->record_from_buff)(&tls_session->clean_in, tlv_packet, 20);
155  tls_handshake_send(eap_session->request, tls_session);
156  return 1;
157 }
158 
159 static void eap_peap_soh_verify(REQUEST *request, RADIUS_PACKET *packet,
160  uint8_t const *data, unsigned int data_len) {
161 
162  VALUE_PAIR *vp;
163  uint8_t eap_method_base;
164  uint32_t eap_vendor;
165  uint32_t eap_method;
166  int rv;
167 
168  vp = fr_pair_make(packet, &packet->vps, "SoH-Supported", "no", T_OP_EQ);
169  if (data && data[0] == PW_EAP_NAK) {
170  RDEBUG("SoH - client NAKed");
171  return;
172  }
173 
174  if (!data || data_len < 8) {
175  RDEBUG("SoH - eap payload too short");
176  return;
177  }
178 
179  eap_method_base = *data++;
180  if (eap_method_base != 254) {
181  RDEBUG("SoH - response is not extended EAP: %i", eap_method_base);
182  return;
183  }
184 
185  eap_vendor = soh_pull_be_24(data); data += 3;
186  if (eap_vendor != 0x137) {
187  RDEBUG("SoH - extended eap vendor %08x is not Microsoft", eap_vendor);
188  return;
189  }
190 
191  eap_method = soh_pull_be_32(data); data += 4;
192  if (eap_method != 0x21) {
193  RDEBUG("SoH - response eap type %08x is not EAP-SoH", eap_method);
194  return;
195  }
196 
197 
198  rv = soh_verify(request, data, data_len - 8);
199  if (rv<0) {
200  RDEBUG("SoH - error decoding payload: %s", fr_strerror());
201  } else {
202  vp->vp_integer = 1;
203  }
204 }
205 
206 /*
207  * Verify the tunneled EAP message.
208  */
209 static int eap_peap_verify(REQUEST *request,
210  uint8_t const *data, unsigned int data_len)
211 {
212  eap_packet_raw_t const *eap_packet = (eap_packet_raw_t const *) data;
214 
215  /*
216  * No data, OR only 1 byte of EAP type.
217  */
218  if (!data || (data_len == 0) ||
219  ((data_len <= 1) && (data[0] != PW_EAP_IDENTITY))) {
220  return 0;
221  }
222 
223  eap_method = *data;
224  switch (eap_method) {
225  case PW_EAP_IDENTITY:
226  if (data_len == 1) {
227  RDEBUG2("Identity - ");
228  return 1;
229  }
230  RDEBUG2("Identity - %*s", data_len - 1, data + 1);
231  return 1;
232 
233  /*
234  * If the first byte of the packet is
235  * EAP-Response, and the EAP data is a TLV,
236  * then it looks OK...
237  */
238  case PW_EAP_RESPONSE:
239  if (eap_packet->data[0] == PW_EAP_TLV) {
240  RDEBUG2("Received EAP-TLV response");
241  return 1;
242  }
243  RDEBUG2("Got something weird");
244  break;
245 
246 
247  /*
248  * We normally do Microsoft MS-CHAPv2 (26), versus
249  * Cisco MS-CHAPv2 (29).
250  */
251  case PW_EAP_MSCHAPV2:
252  default:
253  RDEBUG2("EAP method %s (%d)", eap_type2name(eap_method), eap_method);
254  return 1;
255  }
256 
257  return 0;
258 }
259 
260 /*
261  * Convert a pseudo-EAP packet to a list of VALUE_PAIR's.
262  */
265  uint8_t const *data, size_t data_len)
266 {
267  size_t total;
268  uint8_t *p;
269  VALUE_PAIR *vp = NULL, *head = NULL;
270  vp_cursor_t cursor;
271 
272  if (data_len > 65535) return NULL; /* paranoia */
273 
274  vp = fr_pair_afrom_num(packet, 0, PW_EAP_MESSAGE);
275  if (!vp) {
276  return NULL;
277  }
278 
279  total = data_len;
280  if (total > 249) total = 249;
281 
282  /*
283  * Hand-build an EAP packet from the crap in PEAP version 0.
284  */
285  p = talloc_array(vp, uint8_t, EAP_HEADER_LEN + total);
286  p[0] = PW_EAP_RESPONSE;
287  p[1] = eap_round->response->id;
288  p[2] = (data_len + EAP_HEADER_LEN) >> 8;
289  p[3] = (data_len + EAP_HEADER_LEN) & 0xff;
290  memcpy(p + EAP_HEADER_LEN, data, total);
291  fr_pair_value_memsteal(vp, p);
292 
293  fr_cursor_init(&cursor, &head);
294  fr_cursor_insert(&cursor, vp);
295  while (total < data_len) {
296  vp = fr_pair_afrom_num(packet, 0, PW_EAP_MESSAGE);
297  if (!vp) {
298  fr_pair_list_free(&head);
299  return NULL;
300  }
301 
302  fr_pair_value_memcpy(vp, data + total, (data_len - total));
303 
304  total += vp->vp_length;
305 
306  fr_cursor_insert(&cursor, vp);
307  }
308 
309  return head;
310 }
311 
312 
313 /*
314  * Convert a list of VALUE_PAIR's to an EAP packet, through the
315  * simple expedient of dumping the EAP message
316  */
317 static int eap_peap_inner_from_pairs(REQUEST *request, tls_session_t *tls_session, VALUE_PAIR *vp)
318 {
319  rad_assert(vp != NULL);
320  VALUE_PAIR *this;
321  vp_cursor_t cursor;
322 
323  /*
324  * Skip the id, code, and length. Just write the EAP
325  * type & data to the client.
326  */
327 #ifndef NDEBUG
328  if ((rad_debug_lvl > 2) && fr_log_fp) {
329  size_t i, total, start = EAP_HEADER_LEN;
330  total = 0;
331 
332  for (this = fr_cursor_init(&cursor, &vp); this; this = fr_cursor_next(&cursor)) {
333  for (i = start; i < vp->vp_length; i++) {
334  if ((total & 0x0f) == 0) {
335  fprintf(fr_log_fp, " PEAP tunnel data out %04x: ", (int) total);
336  }
337  fprintf(fr_log_fp, "%02x ", vp->vp_octets[i]);
338 
339  if ((total & 0x0f) == 0x0f) {
340  fprintf(fr_log_fp, "\n");
341  }
342 
343  total++;
344  }
345 
346  start = 0;
347  }
348 
349  if ((total & 0x0f) != 0) {
350  fprintf(fr_log_fp, "\n");
351  }
352  }
353 #endif
354 
355  /*
356  * Send the EAP data in the first attribute, WITHOUT the
357  * header.
358  */
359  (tls_session->record_from_buff)(&tls_session->clean_in, vp->vp_octets + EAP_HEADER_LEN, vp->vp_length - EAP_HEADER_LEN);
360 
361  /*
362  * Send the rest of the EAP data, but skipping the first VP.
363  */
364  fr_cursor_init(&cursor, &vp);
365  for (this = fr_cursor_next(&cursor);
366  this;
367  this = fr_cursor_next(&cursor)) {
368  (tls_session->record_from_buff)(&tls_session->clean_in, this->vp_octets, this->vp_length);
369  }
370 
371  tls_handshake_send(request, tls_session);
372 
373  return 1;
374 }
375 
376 
377 /*
378  * See if there's a TLV in the response.
379  */
380 static int eap_peap_check_tlv(REQUEST *request, uint8_t const *data, size_t data_len)
381 {
382  eap_packet_raw_t const *eap_packet = (eap_packet_raw_t const *) data;
383 
384  if (data_len < 11) return 0;
385 
386  /*
387  * Look for success or failure.
388  */
389  if ((eap_packet->code == PW_EAP_RESPONSE) &&
390  (eap_packet->data[0] == PW_EAP_TLV)) {
391  if (data[10] == EAP_TLV_SUCCESS) {
392  return 1;
393  }
394 
395  if (data[10] == EAP_TLV_FAILURE) {
396  RDEBUG2("Client rejected our response. The password is probably incorrect");
397  return 0;
398  }
399  }
400 
401  RDEBUG("Unknown TLV %02x", data[10]);
402 
403  return 0;
404 }
405 
406 
407 /*
408  * Use a reply packet to determine what to do.
409  */
410 static rlm_rcode_t CC_HINT(nonnull) process_reply(eap_session_t *eap_session, tls_session_t *tls_session,
411  REQUEST *request, RADIUS_PACKET *reply)
412 {
414  VALUE_PAIR *vp;
415  peap_tunnel_t *t = tls_session->opaque;
416 
417  if (RDEBUG_ENABLED2) {
418 
419  /*
420  * Note that we don't do *anything* with the reply
421  * attributes.
422  */
423  if (is_radius_code(reply->code)) {
424  RDEBUG2("Got tunneled reply %s", fr_packet_codes[reply->code]);
425  } else {
426  RDEBUG2("Got tunneled reply code %i", reply->code);
427  }
428  rdebug_pair_list(L_DBG_LVL_2, request, reply->vps, NULL);
429  }
430 
431  switch (reply->code) {
433  RDEBUG2("Tunneled authentication was successful");
435  eap_peap_success(eap_session, tls_session);
436  rcode = RLM_MODULE_HANDLED;
437 
438  /*
439  * If we've been told to use the attributes from
440  * the reply, then do so.
441  *
442  * WARNING: This may leak information about the
443  * tunneled user!
444  */
445  if (t->use_tunneled_reply) {
446  RDEBUG2("Saving tunneled attributes for later");
447 
448  /*
449  * Clean up the tunneled reply.
450  */
451  fr_pair_delete_by_num(&reply->vps, 0, PW_PROXY_STATE, TAG_ANY);
452  fr_pair_delete_by_num(&reply->vps, 0, PW_EAP_MESSAGE, TAG_ANY);
453  fr_pair_delete_by_num(&reply->vps, 0, PW_MESSAGE_AUTHENTICATOR, TAG_ANY);
454 
455  /*
456  * Delete MPPE keys & encryption policy. We don't
457  * want these here.
458  */
463 
464  fr_pair_list_free(&t->accept_vps); /* for proxying MS-CHAP2 */
465  fr_pair_list_mcopy_by_num(t, &t->accept_vps, &reply->vps, 0, 0, TAG_ANY);
466  rad_assert(!reply->vps);
467  }
468  break;
469 
471  RDEBUG2("Tunneled authentication was rejected");
473  eap_peap_failure(eap_session, tls_session);
474  rcode = RLM_MODULE_HANDLED;
475  break;
476 
478  RDEBUG2("Got tunneled Access-Challenge");
479 
480  /*
481  * Keep the State attribute, if necessary.
482  *
483  * Get rid of the old State, too.
484  */
486  fr_pair_list_mcopy_by_num(t, &t->state, &reply->vps, 0, PW_STATE, TAG_ANY);
487 
488  /*
489  * PEAP takes only EAP-Message attributes inside
490  * of the tunnel. Any Reply-Message in the
491  * Access-Challenge is ignored.
492  */
493  vp = NULL;
494  fr_pair_list_mcopy_by_num(t, &vp, &reply->vps, 0, PW_EAP_MESSAGE, TAG_ANY);
495 
496  /*
497  * Handle EAP-MSCHAP-V2, where Access-Accept's
498  * from the home server may contain MS-CHAP2-Success,
499  * which the module turns into challenges, so that
500  * the client may respond to the challenge with
501  * an "ack" packet.
502  */
503  if (t->home_access_accept && t->use_tunneled_reply) {
504  RDEBUG2("Saving tunneled attributes for later");
505 
506  /*
507  * Clean up the tunneled reply.
508  */
509  fr_pair_delete_by_num(&reply->vps, 0, PW_PROXY_STATE, TAG_ANY);
510  fr_pair_delete_by_num(&reply->vps, 0, PW_MESSAGE_AUTHENTICATOR, TAG_ANY);
511 
512  rad_assert(!t->accept_vps);
513  fr_pair_list_mcopy_by_num(t, &t->accept_vps, &reply->vps, 0, 0, TAG_ANY);
514  rad_assert(!reply->vps);
515  }
516 
517  /*
518  * Handle the ACK, by tunneling any necessary reply
519  * VP's back to the client.
520  */
521  if (vp) {
522  eap_peap_inner_from_pairs(request, tls_session, vp);
523  fr_pair_list_free(&vp);
524  }
525 
526  rcode = RLM_MODULE_HANDLED;
527  break;
528 
529  default:
530  RDEBUG2("Unknown RADIUS packet type %d: rejecting tunneled user", reply->code);
531  rcode = RLM_MODULE_REJECT;
532  break;
533  }
534 
535  return rcode;
536 }
537 
538 #ifdef WITH_PROXY
539 /*
540  * Do post-proxy processing,
541  */
542 static int CC_HINT(nonnull) eap_peap_postproxy(eap_session_t *eap_session, void *data)
543 {
544  int rcode;
545  tls_session_t *tls_session = (tls_session_t *) data;
546  REQUEST *fake, *request = eap_session->request;
547 
548  RDEBUG2("Passing reply from proxy back into the tunnel");
549 
550  /*
551  * If there was a fake request associated with the proxied
552  * request, do more processing of it.
553  */
554  fake = (REQUEST *) request_data_get(eap_session->request,
555  eap_session->request->proxy,
557 
558  /*
559  * Do the callback, if it exists, and if it was a success.
560  */
561  if (fake && (eap_session->request->proxy_reply->code == PW_CODE_ACCESS_ACCEPT)) {
562  peap_tunnel_t *t = tls_session->opaque;
563 
564  t->home_access_accept = true;
565 
566  /*
567  * Terrible hacks.
568  */
569  rad_assert(!fake->packet);
570  fake->packet = talloc_steal(fake, request->proxy);
571  fake->packet->src_ipaddr = request->packet->src_ipaddr;
572  request->proxy = NULL;
573 
574  rad_assert(!fake->reply);
575  fake->reply = talloc_steal(fake, request->proxy_reply);
576  request->proxy_reply = NULL;
577 
578  if ((rad_debug_lvl > 0) && fr_log_fp) {
579  fprintf(fr_log_fp, "server %s {\n", fake->server);
580  }
581 
582  /*
583  * Perform a post-auth stage, which will get the EAP
584  * eap_session, too...
585  */
587  RDEBUG2("Passing reply back for EAP-MS-CHAP-V2");
588  process_post_proxy(0, fake);
589 
590  /*
591  * FIXME: If rcode returns fail, do something
592  * intelligent...
593  */
594  rcode = rad_postauth(fake);
595 
596  if ((rad_debug_lvl > 0) && fr_log_fp) {
597  fprintf(fr_log_fp, "} # server %s\n", fake->server);
598 
599  RDEBUG("Final reply from tunneled session code %d", fake->reply->code);
600  rdebug_pair_list(L_DBG_LVL_1, request, fake->reply->vps, NULL);
601  }
602 
603  /*
604  * Terrible hacks.
605  */
606  request->proxy = talloc_steal(request, fake->packet);
607  fake->packet = NULL;
608  request->proxy_reply = talloc_steal(request, fake->reply);
609  fake->reply = NULL;
610 
611  /*
612  * And we're done with this request.
613  */
614 
615  switch (rcode) {
616  case RLM_MODULE_FAIL:
617  talloc_free(fake);
618  eap_tls_fail(eap_session);
619  return 0;
620 
621  default: /* Don't Do Anything */
622  RDEBUG2("Got reply %d", request->proxy_reply->code);
623  break;
624  }
625  }
626  talloc_free(fake); /* robust if !fake */
627 
628  /*
629  * If there was no EAP-Message in the reply packet, then
630  * we know that we're supposed to re-run the "authenticate"
631  * stage, in order to get the right kind of handling...
632  */
633 
634  /*
635  * Process the reply from the home server.
636  */
637 
638  rcode = process_reply(eap_session, tls_session, eap_session->request,
639  eap_session->request->proxy_reply);
640 
641  /*
642  * The proxy code uses the reply from the home server as
643  * the basis for the reply to the NAS. We don't want that,
644  * so we toss it, after we've had our way with it.
645  */
646  fr_pair_list_free(&eap_session->request->proxy_reply->vps);
647 
648  switch (rcode) {
649  case RLM_MODULE_REJECT:
650  RDEBUG2("Reply was rejected");
651  eap_tls_fail(eap_session);
652  return 0;
653 
654  case RLM_MODULE_HANDLED:
655  RDEBUG2("Reply was handled");
656  eap_tls_request(eap_session);
658  return 1;
659 
660  case RLM_MODULE_OK:
661  RDEBUG2("Reply was OK");
662 
663  /*
664  * Success: Automatically return MPPE keys.
665  */
666  if (eap_tls_success(eap_session) < 0) return 0;
667  return 1;
668 
669  default:
670  RDEBUG2("Reply was unknown");
671  break;
672  }
673 
674  eap_tls_fail(eap_session);
675  return 0;
676 }
677 #endif
678 
679 
680 static char const *peap_state(peap_tunnel_t *t)
681 {
682  switch (t->status) {
684  return "TUNNEL ESTABLISHED";
685 
687  return "WAITING FOR SOH RESPONSE";
688 
690  return "WAITING FOR INNER IDENTITY";
691 
693  return "send tlv success";
694 
696  return "send tlv failure";
697 
699  return "phase2_init";
700 
701  case PEAP_STATUS_PHASE2:
702  return "phase2";
703 
704  default:
705  break;
706  }
707  return "?";
708 }
709 
710 static void print_tunneled_data(uint8_t const *data, size_t data_len)
711 {
712  size_t i;
713 
714  if ((rad_debug_lvl > 2) && fr_log_fp) {
715  for (i = 0; i < data_len; i++) {
716  if ((i & 0x0f) == 0) fprintf(fr_log_fp, " PEAP tunnel data in %02x: ", (int) i);
717 
718  fprintf(fr_log_fp, "%02x ", data[i]);
719 
720  if ((i & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n");
721  }
722  if ((data_len & 0x0f) != 0) fprintf(fr_log_fp, "\n");
723  }
724 }
725 
726 
727 /*
728  * Process the pseudo-EAP contents of the tunneled data.
729  */
730 rlm_rcode_t eap_peap_process(eap_session_t *eap_session, tls_session_t *tls_session, int auth_type_eap)
731 {
732  peap_tunnel_t *t = tls_session->opaque;
733  REQUEST *fake;
734  VALUE_PAIR *vp;
736  uint8_t const *data;
737  unsigned int data_len;
738 
739  REQUEST *request = eap_session->request;
740  eap_round_t *eap_round = eap_session->this_round;
741 
742  /*
743  * Just look at the buffer directly, without doing
744  * record_to_buff. This lets us avoid another data copy.
745  */
746  data_len = tls_session->clean_out.used;
747  tls_session->clean_out.used = 0;
748  data = tls_session->clean_out.data;
749 
750  RDEBUG2("PEAP state %s", peap_state(t));
751 
753  !eap_peap_verify(request, data, data_len)) {
754  REDEBUG("Tunneled data is invalid");
755  if (rad_debug_lvl > 2) print_tunneled_data(data, data_len);
756  return RLM_MODULE_REJECT;
757  }
758 
759  switch (t->status) {
761  /* FIXME: should be no data in the buffer here, check & assert? */
762 
763  if (SSL_session_reused(tls_session->ssl)) {
764  RDEBUG2("Skipping Phase2 because of session resumption");
766  if (t->soh) {
768  RDEBUG2("Requesting SoH from client");
769  eap_peap_soh(eap_session, tls_session);
770  return RLM_MODULE_HANDLED;
771  }
772  /* we're good, send success TLV */
774  eap_peap_success(eap_session, tls_session);
775 
776  } else {
777  /* send an identity request */
780  eap_peap_identity(eap_session, tls_session);
781  }
782  return RLM_MODULE_HANDLED;
783 
785  /* we're expecting an identity response */
786  if (data[0] != PW_EAP_IDENTITY) {
787  REDEBUG("Expected EAP-Identity, got something else");
788  return RLM_MODULE_REJECT;
789  }
790 
791  /*
792  * Save it for later.
793  */
794  t->username = fr_pair_make(t, NULL, "User-Name", NULL, T_OP_EQ);
795  rad_assert(t->username != NULL);
796 
797  fr_pair_value_bstrncpy(t->username, data + 1, data_len - 1);
798 
799  RDEBUG("Got inner identity '%s'", t->username->vp_strvalue);
800  if (t->soh) {
802  RDEBUG2("Requesting SoH from client");
803  eap_peap_soh(eap_session, tls_session);
804  return RLM_MODULE_HANDLED;
805  }
807  break;
808 
810  fake = request_alloc_fake(request);
811  rad_assert(!fake->packet->vps);
812  eap_peap_soh_verify(fake, fake->packet, data, data_len);
813  setup_fake_request(request, fake, t);
814 
815  if (t->soh_virtual_server) {
816  fake->server = t->soh_virtual_server;
817  }
818  RDEBUG("Sending SoH request to server %s", fake->server ? fake->server : "NULL");
819  rad_virtual_server(fake);
820 
821  if (fake->reply->code != PW_CODE_ACCESS_ACCEPT) {
822  RDEBUG2("SoH was rejected");
823  talloc_free(fake);
825  eap_peap_failure(eap_session, tls_session);
826  return RLM_MODULE_HANDLED;
827  }
828 
829  /* save the SoH VPs */
831  fr_pair_list_mcopy_by_num(t, &t->soh_reply_vps, &fake->reply->vps, 0, 0, TAG_ANY);
832  rad_assert(!fake->reply->vps);
833  talloc_free(fake);
834 
836  /* we're good, send success TLV */
838  eap_peap_success(eap_session, tls_session);
839  return RLM_MODULE_HANDLED;
840  }
841 
843  break;
844 
845 
846  /*
847  * If we authenticated the user, then it's OK.
848  */
850  if (eap_peap_check_tlv(request, data, data_len)) {
851  RDEBUG2("Success");
852  return RLM_MODULE_OK;
853  }
854 
855  /*
856  * Otherwise, the client rejected the session
857  * resumption. If the session is being re-used,
858  * we need to do a full authentication.
859  *
860  * We do this by sending an EAP-Identity request
861  * inside of the PEAP tunnel.
862  */
864  RDEBUG2("Client rejected session resumption. Re-starting full authentication");
865 
866  /*
867  * Mark session resumption status.
868  */
871 
872  eap_peap_identity(eap_session, tls_session);
873  return RLM_MODULE_HANDLED;
874  }
875 
876  REDEBUG("Sent a success, but received something weird in return");
877  return RLM_MODULE_REJECT;
878 
879  /*
880  * Supplicant ACKs our failure.
881  */
883  RINDENT();
884  RIDEBUG("The users session was previously rejected: returning reject (again.)");
885  RIDEBUG("This means you need to read the PREVIOUS messages in the debug output");
886  RIDEBUG("to find out the reason why the user was rejected");
887  RIDEBUG("Look for \"reject\" or \"fail\". Those earlier messages will tell you");
888  RIDEBUG("what went wrong, and how to fix the problem");
889  REXDENT();
890 
891  return RLM_MODULE_REJECT;
892 
894  RDEBUG("In state machine in phase2 init?");
895 
896  case PEAP_STATUS_PHASE2:
897  break;
898 
899  default:
900  REDEBUG("Unhandled state in peap");
901  return RLM_MODULE_REJECT;
902  }
903 
904  fake = request_alloc_fake(request);
905  rad_assert(!fake->packet->vps);
906 
907  switch (t->status) {
908  /*
909  * If we're in PHASE2_INIT, the phase2 method hasn't been
910  * sent an Identity packet yet; do so from the stored
911  * username and this will kick off the phase2 eap method
912  */
913 
915  size_t len = t->username->vp_length + EAP_HEADER_LEN + 1;
916  uint8_t *q;
917 
919 
920  vp = fr_pair_afrom_num(fake->packet, 0, PW_EAP_MESSAGE);
921 
922  q = talloc_array(vp, uint8_t, len);
923  q[0] = PW_EAP_RESPONSE;
924  q[1] = eap_round->response->id;
925  q[2] = (len >> 8) & 0xff;
926  q[3] = len & 0xff;
927  q[4] = PW_EAP_IDENTITY;
928  memcpy(q + EAP_HEADER_LEN + 1,
929  t->username->vp_strvalue, t->username->vp_length);
930 
931  fr_pair_value_memsteal(vp, q);
932  fr_pair_add(&fake->packet->vps, vp);
933 
934  if (t->default_method != 0) {
935  RDEBUG2("Setting default EAP type for tunneled EAP session");
936  vp = fr_pair_make(fake, &fake->config, "EAP-Type", "0", T_OP_EQ);
937  vp->vp_integer = t->default_method;
938  }
939  break; }
940 
941  case PEAP_STATUS_PHASE2:
942  fake->packet->vps = eap_peap_inner_to_pairs(request, fake->packet,
943  eap_round, data, data_len);
944  if (!fake->packet->vps) {
945  talloc_free(fake);
946  RDEBUG2("Unable to convert tunneled EAP packet to internal server data structures");
947  return RLM_MODULE_REJECT;
948  }
949  break;
950 
951  default:
952  REDEBUG("Invalid state change in PEAP");
953  return RLM_MODULE_REJECT;
954  }
955 
956  RDEBUG2("Got tunneled request");
957  rdebug_pair_list(L_DBG_LVL_2, request, fake->packet->vps, NULL);
958 
959  /*
960  * Update other items in the REQUEST data structure.
961  */
962  if (!t->username) {
963  /*
964  * There's no User-Name in the tunneled session,
965  * so we add one here, by pulling it out of the
966  * EAP-Identity packet.
967  */
968  if ((data[0] == PW_EAP_IDENTITY) && (data_len > 1)) {
969  t->username = fr_pair_make(t, NULL, "User-Name", NULL, T_OP_EQ);
970  rad_assert(t->username != NULL);
971 
972  fr_pair_value_bstrncpy(t->username, data + 1, data_len - 1);
973 
974  RDEBUG2("Got tunneled identity of %s", t->username->vp_strvalue);
975 
976  /*
977  * If there's a default EAP type,
978  * set it here.
979  */
980  if (t->default_method != 0) {
981  RDEBUG2("Setting default EAP type for tunneled EAP session");
982  vp = fr_pair_make(fake, &fake->config, "EAP-Type", "0", T_OP_EQ);
983  vp->vp_integer = t->default_method;
984  }
985  }
986  } /* else there WAS a t->username */
987 
988  setup_fake_request(request, fake, t);
989 
990  /*
991  * Call authentication recursively, which will
992  * do PAP, CHAP, MS-CHAP, etc.
993  */
994  eap_virtual_server(request, fake, eap_session, t->virtual_server);
995 
996  /*
997  * Decide what to do with the reply.
998  */
999  switch (fake->reply->code) {
1000  case 0: /* No reply code, must be proxied... */
1001 #ifdef WITH_PROXY
1002  vp = fr_pair_find_by_num(fake->config, 0, PW_PROXY_TO_REALM, TAG_ANY);
1003 
1004  if (vp) {
1005  eap_tunnel_data_t *tunnel;
1006 
1007  /*
1008  * The tunneled request was NOT handled,
1009  * it has to be proxied. This means that
1010  * the "authenticate" stage was never
1011  * performed.
1012  *
1013  * If we are told to NOT proxy the
1014  * tunneled request as EAP, then this
1015  * means that we've got to decode it,
1016  * which means that we MUST run the
1017  * "authenticate" portion by hand, here.
1018  *
1019  * Once the tunneled EAP session is ALMOST
1020  * done, THEN we proxy it...
1021  */
1024 
1025  /*
1026  * Hmm... should we check for
1027  * Auth-Type & EAP-Message here?
1028  */
1029 
1030 
1031  /*
1032  * Run the EAP authentication.
1033  */
1034  RDEBUG2("Calling authenticate in order to initiate tunneled EAP session");
1035  rcode = process_authenticate(auth_type_eap, fake);
1036  if (rcode == RLM_MODULE_OK) {
1037  /*
1038  * Authentication succeeded! Rah!
1039  */
1040  fake->reply->code = PW_CODE_ACCESS_ACCEPT;
1041  goto do_process;
1042  }
1043 
1044  if (rcode != RLM_MODULE_HANDLED) {
1045  RDEBUG("Can't handle the return code %d", rcode);
1046  rcode = RLM_MODULE_REJECT;
1047  goto done;
1048  }
1049 
1050  /*
1051  * The module decided it wasn't
1052  * done. Handle it like normal.
1053  */
1054  if ((fake->options & RAD_REQUEST_OPTION_PROXY_EAP) == 0) {
1055  RDEBUG2("Cancelling proxy to realm %s until the tunneled EAP session "
1056  "has been established", vp->vp_strvalue);
1057  goto do_process;
1058  }
1059 
1060  /*
1061  * The module has decoded the
1062  * EAP-Message into another set
1063  * of attributes.
1064  */
1065  fr_pair_delete_by_num(&fake->packet->vps, 0, PW_EAP_MESSAGE, TAG_ANY);
1066  }
1067 
1068  RDEBUG2("Tunnelled authentication will be proxied to %s", vp->vp_strvalue);
1069 
1070  /*
1071  * Tell the original request that it's going
1072  * to be proxied.
1073  */
1074  fr_pair_list_mcopy_by_num(request, &request->config, &fake->config, 0, PW_PROXY_TO_REALM,
1075  TAG_ANY);
1076 
1077  /*
1078  * Seed the proxy packet with the
1079  * tunneled request.
1080  */
1081  rad_assert(!request->proxy);
1082  request->proxy = talloc_steal(request, fake->packet);
1083  memset(&request->proxy->src_ipaddr, 0,
1084  sizeof(request->proxy->src_ipaddr));
1085  memset(&request->proxy->dst_ipaddr, 0,
1086  sizeof(request->proxy->dst_ipaddr));
1087  request->proxy->src_port = 0;
1088  request->proxy->dst_port = 0;
1089  fake->packet = NULL;
1090  fr_radius_free(&fake->reply);
1091  fake->reply = NULL;
1092 
1093  /*
1094  * Set up the callbacks for the tunnel
1095  */
1096  tunnel = talloc_zero(request, eap_tunnel_data_t);
1097  tunnel->tls_session = tls_session;
1098  tunnel->callback = eap_peap_postproxy;
1099 
1100  /*
1101  * Associate the callback with the request.
1102  */
1103  rcode = request_data_add(request, request->proxy, REQUEST_DATA_EAP_TUNNEL_CALLBACK,
1104  tunnel, false, false, false);
1105  rad_assert(rcode == 0);
1106 
1107  /*
1108  * We're not proxying it as EAP, so we've got
1109  * to do the callback later.
1110  */
1111  if ((fake->options & RAD_REQUEST_OPTION_PROXY_EAP) != 0) {
1112  RDEBUG2("Remembering to do EAP-MS-CHAP-V2 post-proxy");
1113 
1114  /*
1115  * rlm_eap.c has taken care of associating
1116  * the eap_session with the fake request.
1117  *
1118  * So we associate the fake request with
1119  * this request.
1120  */
1121  rcode = request_data_add(request, request->proxy,
1123  fake, true, false, false);
1124  rad_assert(rcode == 0);
1125 
1126  /*
1127  * Do NOT free the fake request!
1128  */
1129  return RLM_MODULE_UPDATED;
1130  }
1131 
1132  /*
1133  * Didn't authenticate the packet, but
1134  * we're proxying it.
1135  */
1136  rcode = RLM_MODULE_UPDATED;
1137 
1138  } else
1139 #endif /* WITH_PROXY */
1140  {
1141  REDEBUG("Unknown RADIUS packet type %d: rejecting tunneled user", fake->reply->code);
1142  rcode = RLM_MODULE_REJECT;
1143  }
1144  break;
1145 
1146  default:
1147 #ifdef WITH_PROXY
1148  do_process:
1149 #endif
1150  rcode = process_reply(eap_session, tls_session, request, fake->reply);
1151  break;
1152  }
1153 
1154 #ifdef WITH_PROXY
1155  done:
1156 #endif
1157  talloc_free(fake);
1158 
1159  return rcode;
1160 }
1161 
1162 static int CC_HINT(nonnull) setup_fake_request(REQUEST *request, REQUEST *fake, peap_tunnel_t *t) {
1163 
1164  VALUE_PAIR *vp;
1165 
1166  /*
1167  * Tell the request that it's a fake one.
1168  */
1169  fr_pair_make(fake->packet, &fake->packet->vps, "Freeradius-Proxied-To", "127.0.0.1", T_OP_EQ);
1170 
1171  if (t->username) {
1172  vp = fr_pair_list_copy(fake->packet, t->username);
1173  fr_pair_add(&fake->packet->vps, vp);
1174  fake->username = vp;
1175  RDEBUG2("Setting &request:User-Name from tunnel (protected) identity \"%s\"",
1176  fake->username->vp_strvalue);
1177  } else {
1178  RDEBUG2("No tunnel username (SSL resumption?)");
1179  }
1180 
1181 
1182  /*
1183  * Add the State attribute, too, if it exists.
1184  */
1185  if (t->state) {
1186  vp = fr_pair_list_copy(fake->packet, t->state);
1187  if (vp) fr_pair_add(&fake->packet->vps, vp);
1188  }
1189 
1190  /*
1191  * If this is set, we copy SOME of the request attributes
1192  * from outside of the tunnel to inside of the tunnel.
1193  *
1194  * We copy ONLY those attributes which do NOT already
1195  * exist in the tunneled request.
1196  *
1197  * This code is copied from ../rlm_eap_ttls/ttls.c
1198  */
1199  if (t->copy_request_to_tunnel) {
1200  VALUE_PAIR *copy;
1201  vp_cursor_t cursor;
1202 
1203  for (vp = fr_cursor_init(&cursor, &request->packet->vps);
1204  vp;
1205  vp = fr_cursor_next(&cursor)) {
1206  /*
1207  * The attribute is a server-side thingy,
1208  * don't copy it.
1209  */
1210  if ((vp->da->attr > 255) && (((vp->da->attr >> 16) & 0xffff) == 0)) {
1211  continue;
1212  }
1213 
1214  /*
1215  * The outside attribute is already in the
1216  * tunnel, don't copy it.
1217  *
1218  * This works for BOTH attributes which
1219  * are originally in the tunneled request,
1220  * AND attributes which are copied there
1221  * from below.
1222  */
1223  if (fr_pair_find_by_da(fake->packet->vps, vp->da, TAG_ANY)) continue;
1224 
1225  /*
1226  * Some attributes are handled specially.
1227  */
1228  switch (vp->da->attr) {
1229  /*
1230  * NEVER copy Message-Authenticator,
1231  * EAP-Message, or State. They're
1232  * only for outside of the tunnel.
1233  */
1234  case PW_USER_NAME:
1235  case PW_USER_PASSWORD:
1236  case PW_CHAP_PASSWORD:
1237  case PW_CHAP_CHALLENGE:
1238  case PW_PROXY_STATE:
1239  case PW_MESSAGE_AUTHENTICATOR:
1240  case PW_EAP_MESSAGE:
1241  case PW_STATE:
1242  continue;
1243 
1244  /*
1245  * By default, copy it over.
1246  */
1247  default:
1248  break;
1249  }
1250 
1251  /*
1252  * Don't copy from the head, we've already
1253  * checked it.
1254  */
1255  copy = fr_pair_list_copy_by_num(fake->packet, vp, vp->da->vendor, vp->da->attr, TAG_ANY);
1256  fr_pair_add(&fake->packet->vps, copy);
1257  }
1258  }
1259 
1260  return 0;
1261 }
void fr_pair_list_free(VALUE_PAIR **)
Free memory used by a valuepair list.
Definition: pair.c:544
uint8_t id
Definition: eap_types.h:145
rlm_rcode_t eap_virtual_server(REQUEST *request, REQUEST *fake, eap_session_t *eap_session, char const *virtual_server)
Send a fake request to a virtual server, managing the eap_session_t of the child. ...
Definition: eapcommon.c:418
2nd highest priority debug messages (-xx | -X).
Definition: log.h:52
FILE * fr_log_fp
Definition: radius.c:81
VALUE_PAIR * config
VALUE_PAIR (s) used to set per request parameters for modules and the server core at runtime...
Definition: radiusd.h:227
#define RINDENT()
Indent R* messages by one level.
Definition: log.h:265
static VALUE_PAIR * eap_peap_inner_to_pairs(UNUSED REQUEST *request, RADIUS_PACKET *packet, eap_round_t *eap_round, uint8_t const *data, size_t data_len)
Definition: peap.c:263
RFC2865 - Access-Challenge.
Definition: radius.h:102
bool proxy_tunneled_request_as_eap
Definition: eap_peap.h:57
RADIUS_PACKET * proxy_reply
Incoming response from proxy server.
Definition: radiusd.h:238
#define EAP_TLV_ACK_RESULT
Definition: eap_peap.h:68
The module is OK, continue.
Definition: radiusd.h:91
VALUE_PAIR * fr_pair_afrom_num(TALLOC_CTX *ctx, unsigned int vendor, unsigned int attr)
Create a new valuepair.
Definition: pair.c:106
#define RAD_REQUEST_OPTION_PROXY_EAP
Definition: eap.h:111
#define RDEBUG_ENABLED2
True if request debug level 1-2 messages are enabled.
Definition: log.h:238
char const * fr_packet_codes[FR_MAX_PACKET_CODE]
Definition: radius.c:101
int rad_postauth(REQUEST *)
Definition: auth.c:287
void fr_pair_list_mcopy_by_num(TALLOC_CTX *ctx, VALUE_PAIR **to, VALUE_PAIR **from, unsigned int vendor, unsigned int attr, int8_t tag)
Copy / delete matching pairs between VALUE_PAIR lists.
Definition: pair.c:1823
#define PW_EAP_TLV
Definition: eap_peap.h:70
static void print_tunneled_data(uint8_t const *data, size_t data_len)
Definition: peap.c:710
static int eap_peap_soh(eap_session_t *eap_session, tls_session_t *tls_session)
Definition: peap.c:123
fr_ipaddr_t src_ipaddr
Src IP address of packet.
Definition: libradius.h:149
char const * soh_virtual_server
Definition: eap_peap.h:60
#define UNUSED
Definition: libradius.h:134
#define REQUEST_DATA_EAP_TUNNEL_CALLBACK
Definition: eap.h:109
VALUE_PAIR * vps
Result of decoding the packet into VALUE_PAIRs.
Definition: libradius.h:162
int default_method
Definition: eap_peap.h:54
uint8_t code
Definition: eap_types.h:144
#define EAP_HEADER_LEN
Definition: eap_types.h:35
VALUE_PAIR * fr_cursor_init(vp_cursor_t *cursor, VALUE_PAIR *const *node)
Setup a cursor to iterate over attribute pairs.
Definition: cursor.c:60
rlm_rcode_t eap_peap_process(eap_session_t *eap_session, tls_session_t *tls_session, int auth_type_eap)
Definition: peap.c:730
Definition: token.h:46
static int eap_peap_check_tlv(REQUEST *request, uint8_t const *data, size_t data_len)
Definition: peap.c:380
VALUE_PAIR * fr_pair_list_copy_by_num(TALLOC_CTX *ctx, VALUE_PAIR *from, unsigned int vendor, unsigned int attr, int8_t tag)
Copy matching pairs.
Definition: pair.c:1428
uint16_t dst_port
DST Port of packet.
Definition: libradius.h:152
uint16_t src_port
Src port of packet.
Definition: libradius.h:151
fr_ipaddr_t dst_ipaddr
Dst IP address of packet.
Definition: libradius.h:150
REQUEST * request_alloc_fake(REQUEST *oldreq)
Definition: request.c:124
static char const * peap_state(peap_tunnel_t *t)
Definition: peap.c:680
Abstraction to allow iterating over different configurations of VALUE_PAIRs.
Definition: pair.h:144
REQUEST * request
Request that contains the response we're processing.
Definition: eap.h:71
#define VENDORPEC_MICROSOFT
Definition: radius.h:200
RADIUS_PACKET * proxy
Outgoing request to proxy server.
Definition: radiusd.h:237
RFC2865 - Access-Reject.
Definition: radius.h:94
VALUE_PAIR * state
Definition: eap_peap.h:50
static int eap_peap_failure(eap_session_t *eap_session, tls_session_t *tls_session)
Definition: peap.c:36
enum eap_method eap_type_t
#define rad_assert(expr)
Definition: rad_assert.h:38
VALUE_PAIR * soh_reply_vps
Definition: eap_peap.h:61
peap_resumption session_resumption_state
Definition: eap_peap.h:62
static int eap_peap_identity(eap_session_t *eap_session, tls_session_t *tls_session)
Definition: peap.c:101
uint32_t soh_pull_be_32(uint8_t const *p)
Read big-endian 4-byte unsigned from p.
Definition: soh.c:118
Highest priority debug messages (-x).
Definition: log.h:51
VALUE_PAIR * fr_pair_list_copy(TALLOC_CTX *ctx, VALUE_PAIR *from)
Copy a pairlist.
Definition: pair.c:1394
uint32_t soh_pull_be_24(uint8_t const *p)
Read big-endian 3-byte unsigned from p.
Definition: soh.c:104
char const * virtual_server
Definition: eap_peap.h:58
uint8_t id
Definition: eap_types.h:134
eap_method
Definition: eap_types.h:45
Structure to represent packet format of eap on wire
Definition: eap_types.h:143
static USES_APPLE_DEPRECATED_API int setup_fake_request(REQUEST *request, REQUEST *fake, peap_tunnel_t *t)
void fr_cursor_insert(vp_cursor_t *cursor, VALUE_PAIR *vp)
Insert a single VALUE_PAIR at the end of the list.
Definition: cursor.c:321
rlm_rcode_t process_authenticate(int type, REQUEST *request)
Definition: modules.c:2106
void fr_pair_add(VALUE_PAIR **head, VALUE_PAIR *vp)
Add a VP to the end of the list.
Definition: pair.c:659
int eap_tls_success(eap_session_t *eap_session)
Send an EAP-TLS success.
Definition: eap_tls.c:211
Tracks the progress of a single session of any EAP method.
Definition: eap.h:60
unsigned int attr
Attribute number.
Definition: dict.h:79
static bool done
Definition: radclient.c:53
Immediately reject the request.
Definition: radiusd.h:89
unsigned int code
Packet code (type).
Definition: libradius.h:155
eap_round_t * this_round
The EAP response we're processing, and the EAP request we're building.
Definition: eap.h:77
void * request_data_get(REQUEST *request, void *unique_ptr, int unique_int)
Get opaque data from a request.
Definition: request.c:374
VALUE_PAIR * username
Definition: eap_peap.h:49
RFC2865 - Access-Accept.
Definition: radius.h:93
void * tls_session
Definition: eap.h:119
bool use_tunneled_reply
Definition: eap_peap.h:56
unsigned int vendor
Vendor that defines this attribute.
Definition: dict.h:78
Stores an attribute, a value and various bits of other data.
Definition: pair.h:112
eap_tunnel_callback_t callback
Definition: eap.h:120
rlm_rcode_t process_post_proxy(int type, REQUEST *request)
Definition: modules.c:2169
RADIUS_PACKET * reply
Outgoing response.
Definition: radiusd.h:225
static int eap_peap_inner_from_pairs(REQUEST *request, tls_session_t *tls_session, VALUE_PAIR *vp)
Definition: peap.c:317
#define REXDENT()
Exdent (unindent) R* messages by one level.
Definition: log.h:272
uint8_t length[2]
Definition: eap_types.h:146
uint8_t data[1]
Definition: eap_types.h:147
enum rlm_rcodes rlm_rcode_t
Return codes indicating the result of the module call.
Contains a pair of request and response packets.
Definition: eap.h:43
char const * fr_strerror(void)
Get the last library error.
Definition: log.c:212
static int eap_peap_verify(REQUEST *request, uint8_t const *data, unsigned int data_len)
Definition: peap.c:209
void rdebug_pair_list(log_lvl_t level, REQUEST *, VALUE_PAIR *, char const *)
Print a list of VALUE_PAIRs.
Definition: pair.c:757
void fr_pair_delete_by_num(VALUE_PAIR **head, unsigned int vendor, unsigned int attr, int8_t tag)
Delete matching pairs.
Definition: pair.c:797
#define EAP_TLV_SUCCESS
Definition: eap_peap.h:66
VALUE_PAIR * fr_pair_find_by_da(VALUE_PAIR *head, fr_dict_attr_t const *da, int8_t tag)
Find the pair with the matching DAs.
Definition: pair.c:624
#define RDEBUG2(fmt,...)
Definition: log.h:244
uint8_t data[]
Definition: eap_pwd.h:625
#define RIDEBUG(fmt,...)
Definition: log.h:248
Module failed, don't reply.
Definition: radiusd.h:90
char const * eap_type2name(eap_type_t method)
Return an EAP-name for a particular type.
Definition: eapcommon.c:104
void fr_pair_value_memsteal(VALUE_PAIR *vp, uint8_t const *src)
Reparent an allocated octet buffer to a VALUE_PAIR.
Definition: pair.c:1933
#define TAG_ANY
Definition: pair.h:191
int soh_verify(REQUEST *request, uint8_t const *data, unsigned int data_len) CC_HINT(nonnull)
Parse the MS-SOH response in data and update sohvp.
Definition: soh.c:385
static const void * fake
Definition: rlm_sql_null.c:33
log_lvl_t rad_debug_lvl
Global debugging level.
Definition: log.c:49
static rlm_rcode_t CC_HINT(nonnull)
Definition: peap.c:410
VALUE_PAIR * fr_cursor_next(vp_cursor_t *cursor)
Advanced the cursor to the next VALUE_PAIR.
Definition: cursor.c:263
bool home_access_accept
Definition: eap_peap.h:53
void fr_radius_free(RADIUS_PACKET **)
Free a RADIUS_PACKET.
Definition: radius.c:1727
VALUE_PAIR * accept_vps
Definition: eap_peap.h:51
RADIUS_PACKET * packet
Incoming request.
Definition: radiusd.h:221
int request_data_add(REQUEST *request, void *unique_ptr, int unique_int, void *opaque, bool free_on_replace, bool free_on_parent, bool persist)
Add opaque data to a REQUEST.
Definition: request.c:279
#define REDEBUG(fmt,...)
Definition: log.h:254
VALUE_PAIR * fr_pair_find_by_num(VALUE_PAIR *head, unsigned int vendor, unsigned int attr, int8_t tag)
Find the pair with the matching attribute.
Definition: pair.c:639
int eap_tls_fail(eap_session_t *eap_session)
Send an EAP-TLS failure.
Definition: eap_tls.c:254
Structure to hold EAP data.
Definition: eap_types.h:132
fr_dict_attr_t const * da
Dictionary attribute defines the attribute.
Definition: pair.h:113
void fr_pair_value_bstrncpy(VALUE_PAIR *vp, void const *src, size_t len)
Copy data into an "string" data type.
Definition: pair.c:2043
eap_packet_t * response
Packet we received from the peer.
Definition: eap.h:44
#define RCSID(id)
Definition: build.h:135
int rad_virtual_server(REQUEST *)
Definition: auth.c:659
int eap_tls_request(eap_session_t *eap_session)
Frames the OpenSSL data that needs to be sent to the client in an EAP-Request.
Definition: eap_tls.c:299
OK (pairs modified).
Definition: radiusd.h:97
The module handled the request, so stop.
Definition: radiusd.h:92
peap_status status
Definition: eap_peap.h:52
VALUE_PAIR * fr_pair_make(TALLOC_CTX *ctx, VALUE_PAIR **vps, char const *attribute, char const *value, FR_TOKEN op)
Create a VALUE_PAIR from ASCII strings.
Definition: pair.c:338
#define RDEBUG(fmt,...)
Definition: log.h:243
uint32_t options
mainly for proxying EAP-MSCHAPv2.
Definition: radiusd.h:304
#define is_radius_code(_x)
Definition: libradius.h:372
#define EAP_TLV_FAILURE
Definition: eap_peap.h:67
static int eap_peap_success(eap_session_t *eap_session, tls_session_t *tls_session)
Definition: peap.c:71
void fr_pair_value_memcpy(VALUE_PAIR *vp, uint8_t const *src, size_t len)
Copy data into an "octets" data type.
Definition: pair.c:1905
char const * server
Definition: radiusd.h:289
#define USES_APPLE_DEPRECATED_API
Definition: build.h:122
static void eap_peap_soh_verify(REQUEST *request, RADIUS_PACKET *packet, uint8_t const *data, unsigned int data_len)
Definition: peap.c:159
#define REQUEST_DATA_EAP_MSCHAP_TUNNEL_CALLBACK
Definition: eap.h:110