The FreeRADIUS server $Id: f3670dba8951ca10eb4948feb3dc3db9423a334f $
Loading...
Searching...
No Matches
rlm_eap_peap.c
Go to the documentation of this file.
1/*
2 * rlm_eap_peap.c contains the interfaces that are called from eap
3 *
4 * Version: $Id: 8c3b221dc65d61e2adc4e00884d8c7f136e29a29 $
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 */
23RCSID("$Id: 8c3b221dc65d61e2adc4e00884d8c7f136e29a29 $")
24
25#include <freeradius-devel/eap/tls.h>
26
27typedef struct {
28 SSL_CTX *ssl_ctx; //!< Thread local SSL_CTX.
30
31typedef struct {
32 char const *tls_conf_name; //!< TLS configuration.
33 fr_tls_conf_t *tls_conf;
34
35 bool use_tunneled_reply; //!< Use the reply attributes from the tunneled session in
36 //!< the non-tunneled reply to the client.
37
38 bool copy_request_to_tunnel; //!< Use SOME of the request attributes from outside of the
39 //!< tunneled session in the tunneled request.
40
41 virtual_server_t *virtual_server; //!< Virtual server for inner tunnel session.
43
44 bool req_client_cert; //!< Do we do require a client cert?
46
56
62
70
71#define EAP_TLV_SUCCESS (1)
72#define EAP_TLV_FAILURE (2)
73#define EAP_TLV_ACK_RESULT (3)
74
75#define FR_PEAP_EXTENSIONS_TYPE 33
76
78 { FR_CONF_OFFSET("tls", rlm_eap_peap_t, tls_conf_name) },
79
80 { FR_CONF_DEPRECATED("copy_request_to_tunnel", rlm_eap_peap_t, NULL), .dflt = "no" },
81
82 { FR_CONF_DEPRECATED("use_tunneled_reply", rlm_eap_peap_t, NULL), .dflt = "no" },
83
86 .uctx = &(virtual_server_cf_parse_uctx_t){ .process_module_name = "radius"} },
87 { FR_CONF_OFFSET("require_client_cert", rlm_eap_peap_t, req_client_cert), .dflt = "no" },
88
90};
91
93static fr_dict_t const *dict_radius;
94
97 { .out = &dict_freeradius, .proto = "freeradius" },
98 { .out = &dict_radius, .proto = "radius" },
100};
101
104
107
110 { .out = &attr_auth_type, .name = "Auth-Type", .type = FR_TYPE_UINT32, .dict = &dict_freeradius },
111 { .out = &attr_eap_tls_require_client_cert, .name = "EAP-TLS-Require-Client-Cert", .type = FR_TYPE_UINT32, .dict = &dict_freeradius },
112
113 { .out = &attr_eap_message, .name = "EAP-Message", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
114 { .out = &attr_user_name, .name = "User-Name", .type = FR_TYPE_STRING, .dict = &dict_radius },
116};
117
118
119/*
120 * Send protected EAP-Failure
121 *
122 * Result-TLV = Failure
123 */
124static int eap_peap_failure(request_t *request, eap_session_t *eap_session, fr_tls_session_t *tls_session)
125{
126 uint8_t tlv_packet[11];
127
128 RDEBUG2("FAILURE");
129
130 tlv_packet[0] = FR_EAP_CODE_REQUEST;
131 tlv_packet[1] = eap_session->this_round->response->id +1;
132 tlv_packet[2] = 0;
133 tlv_packet[3] = 11; /* length of this packet */
134 tlv_packet[4] = FR_PEAP_EXTENSIONS_TYPE;
135 tlv_packet[5] = 0x80;
136 tlv_packet[6] = EAP_TLV_ACK_RESULT;
137 tlv_packet[7] = 0;
138 tlv_packet[8] = 2; /* length of the data portion */
139 tlv_packet[9] = 0;
140 tlv_packet[10] = EAP_TLV_FAILURE;
141
142 (tls_session->record_from_buff)(&tls_session->clean_in, tlv_packet, 11);
143
144 return fr_tls_session_send(request, tls_session);
145}
146
147/*
148 * Send protected EAP-Success
149 *
150 * Result-TLV = Success
151 */
152static int eap_peap_success(request_t *request, eap_session_t *eap_session, fr_tls_session_t *tls_session)
153{
154 uint8_t tlv_packet[11];
155
156 RDEBUG2("SUCCESS");
157
158 tlv_packet[0] = FR_EAP_CODE_REQUEST;
159 tlv_packet[1] = eap_session->this_round->response->id +1;
160 tlv_packet[2] = 0;
161 tlv_packet[3] = 11; /* length of this packet */
162 tlv_packet[4] = FR_PEAP_EXTENSIONS_TYPE;
163 tlv_packet[5] = 0x80; /* mandatory AVP */
164 tlv_packet[6] = EAP_TLV_ACK_RESULT;
165 tlv_packet[7] = 0;
166 tlv_packet[8] = 2; /* length of the data portion */
167 tlv_packet[9] = 0;
168 tlv_packet[10] = EAP_TLV_SUCCESS;
169
170 (tls_session->record_from_buff)(&tls_session->clean_in, tlv_packet, 11);
171
172 return fr_tls_session_send(request, tls_session);
173}
174
175
176static int eap_peap_identity(request_t *request, eap_session_t *eap_session, fr_tls_session_t *tls_session)
177{
178 eap_packet_hdr_t eap_packet;
179
180 eap_packet.code = FR_EAP_CODE_REQUEST;
181 eap_packet.id = eap_session->this_round->response->id + 1;
182 eap_packet.length[0] = 0;
183 eap_packet.length[1] = EAP_HEADER_LEN + 1;
184 eap_packet.data[0] = FR_EAP_METHOD_IDENTITY;
185
186 (tls_session->record_from_buff)(&tls_session->clean_in, &eap_packet, sizeof(eap_packet));
187 return fr_tls_session_send(request, tls_session);
188}
189
190/*
191 * Verify the tunneled EAP message.
192 */
193static int eap_peap_verify(request_t *request, peap_tunnel_t *peap_tunnel,
194 uint8_t const *data, size_t data_len)
195{
196 eap_packet_raw_t const *eap_packet = (eap_packet_raw_t const *) data;
197 eap_type_t eap_method;
198
199 /*
200 * No data, OR only 1 byte of EAP type.
201 */
202 if (!data || !data_len || (data[0] != FR_EAP_METHOD_IDENTITY)) return 0;
203
204 /*
205 * Since the full EAP header is sent for the EAP Extensions type (Type 33),
206 * but not for other Types, it is difficult for the implementation to distinguish
207 * an Extensions Request (Code 1) from an EAP Type 1 (Identity) Request packet.
208 *
209 * i.e. The only way to validate PEAP inner method packets properly is to know
210 * we just send a protected success/failure.
211 */
212 switch (peap_tunnel->status) {
215 if (data_len < 5) {
216 REDEBUG("Peer sent too-short EAP packet in PEAP Extensions exchange (%zu < 5)", data_len);
217 return -1;
218 }
219
220 if (eap_packet->data[0] != FR_PEAP_EXTENSIONS_TYPE) {
221 REDEBUG("Invalid inner tunnel data, expected method (%u), got (%u)",
222 FR_PEAP_EXTENSIONS_TYPE, eap_packet->data[0]);
223 return -1;
224 }
225 return 0;
226
227 default:
228 break;
229 }
230
231 eap_method = data[0]; /* Inner EAP header misses off code and identifier */
232 switch (eap_method) {
234 RDEBUG2("Received EAP-Identity-Response");
235 return 0;
236
237 /*
238 * We normally do Microsoft MS-CHAPv2 (26), versus
239 * Cisco MS-CHAPv2 (29).
240 */
242 default:
243 RDEBUG2("EAP method %s (%d)", eap_type2name(eap_method), eap_method);
244 return 0;
245 }
246
247}
248
249/*
250 * Convert a pseudo-EAP packet to a list of fr_pair_t's.
251 */
252static void eap_peap_inner_to_pairs(TALLOC_CTX *ctx, fr_pair_list_t *pairs,
253 eap_round_t *eap_round,
254 uint8_t const *data, size_t data_len)
255{
256 size_t total;
257 uint8_t *p;
258 fr_pair_t *vp = NULL;
259
260 if (data_len > 65535) return; /* paranoia */
261
263 total = data_len;
264 if (total > 249) total = 249;
265
266 /*
267 * Hand-build an EAP packet from the crap in PEAP version 0.
268 */
269 MEM(fr_pair_value_mem_alloc(vp, &p, EAP_HEADER_LEN + total, false) == 0);
271 p[1] = eap_round->response->id;
272 p[2] = (data_len + EAP_HEADER_LEN) >> 8;
273 p[3] = (data_len + EAP_HEADER_LEN) & 0xff;
274 memcpy(p + EAP_HEADER_LEN, data, total);
275
276 fr_pair_append(pairs, vp);
277 while (total < data_len) {
279 fr_pair_value_memdup(vp, data + total, (data_len - total), false);
280
281 total += vp->vp_length;
282
283 fr_pair_append(pairs, vp);
284 }
285}
286
287
288/*
289 * Convert a list of fr_pair_t's to an EAP packet, through the
290 * simple expedient of dumping the EAP message
291 */
292static int eap_peap_inner_from_pairs(request_t *request, fr_tls_session_t *tls_session, fr_pair_list_t *vps)
293{
294 fr_pair_t *this;
295
297 /*
298 * Send the EAP data in the first attribute, WITHOUT the
299 * header.
300 */
301 this = fr_pair_list_head(vps);
302 if (this->vp_length <= EAP_HEADER_LEN) return 1;
303
304 (tls_session->record_from_buff)(&tls_session->clean_in, this->vp_octets + EAP_HEADER_LEN,
305 this->vp_length - EAP_HEADER_LEN);
306
307 /*
308 * Send the rest of the EAP data, but skipping the first VP.
309 */
310 for (this = fr_pair_list_next(vps, this);
311 this;
312 this = fr_pair_list_next(vps, this)) {
313 (tls_session->record_from_buff)(&tls_session->clean_in, this->vp_octets, this->vp_length);
314 }
315
316 fr_tls_session_send(request, tls_session);
317
318 return 1;
319}
320
321
322/*
323 * See if there's a TLV in the response.
324 */
325static int eap_peap_check_tlv(request_t *request, uint8_t const *data, size_t data_len)
326{
327 eap_packet_raw_t const *eap_packet = (eap_packet_raw_t const *) data;
328
329 if (data_len < 11) return 0;
330
331 /*
332 * Look for success or failure.
333 */
334 if ((eap_packet->code == FR_EAP_CODE_RESPONSE) &&
335 (eap_packet->data[0] == FR_PEAP_EXTENSIONS_TYPE)) {
336 if (data[10] == EAP_TLV_SUCCESS) {
337 return 1;
338 }
339
340 if (data[10] == EAP_TLV_FAILURE) {
341 RDEBUG2("Client rejected our response. The password is probably incorrect");
342 return 0;
343 }
344 }
345
346 RDEBUG2("Unknown TLV %02x", data[10]);
347
348 return 0;
349}
350
351
352/*
353 * Use a reply packet to determine what to do.
354 */
355static unlang_action_t process_reply(unlang_result_t *p_result, request_t *request, void *uctx)
356{
357 eap_session_t *eap_session = talloc_get_type_abort(uctx, eap_session_t);
358 eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
359 fr_tls_session_t *tls_session = eap_tls_session->tls_session;
360 fr_pair_list_t vps;
361 peap_tunnel_t *t = tls_session->opaque;
362 request_t *parent = request->parent;
363 fr_packet_t *reply = request->reply;
364
365 p_result->priority = MOD_PRIORITY_MAX;
366
367 if (RDEBUG_ENABLED2) {
368
369 /*
370 * Note that we don't do *anything* with the reply
371 * attributes.
372 */
373 if (FR_RADIUS_PACKET_CODE_VALID(reply->code)) {
374 RDEBUG2("Got tunneled reply %s", fr_radius_packet_name[reply->code]);
375 } else {
376 RDEBUG2("Got tunneled reply code %i", reply->code);
377 }
378 log_request_pair_list(L_DBG_LVL_2, request, NULL, &request->reply_pairs, NULL);
379 }
380
381 switch (reply->code) {
384 if (eap_peap_success(request, eap_session, tls_session) < 0) RETURN_UNLANG_FAIL;
386
389 if (eap_peap_failure(request, eap_session, tls_session) < 0) RETURN_UNLANG_FAIL;
391
393 /*
394 * PEAP takes only EAP-Message attributes inside
395 * of the tunnel. Any Reply-Message in the
396 * Access-Challenge is ignored.
397 */
398 fr_pair_list_init(&vps);
399 MEM(fr_pair_list_copy_by_da(t, &vps, &request->reply_pairs, attr_eap_message, 0) >= 0);
400
401 /*
402 * Handle the ACK, by tunneling any necessary reply
403 * VP's back to the client.
404 */
405 if (!fr_pair_list_empty(&vps)) {
406 eap_peap_inner_from_pairs(parent, tls_session, &vps);
407 fr_pair_list_free(&vps);
408 }
410
411 default:
412 REDEBUG2("Unknown RADIUS packet type %d: rejecting tunneled user", reply->code);
414 }
415}
416
417
418static char const *peap_state(peap_tunnel_t *t)
419{
420 switch (t->status) {
422 return "TUNNEL ESTABLISHED";
423
425 return "WAITING FOR INNER IDENTITY";
426
428 return "send tlv success";
429
431 return "send tlv failure";
432
434 return "phase2_init";
435
437 return "phase2";
438
439 default:
440 break;
441 }
442 return "?";
443}
444
445/*
446 * Process the pseudo-EAP contents of the tunneled data.
447 */
449 eap_session_t *eap_session, fr_tls_session_t *tls_session)
450{
451 peap_tunnel_t *t = tls_session->opaque;
452 request_t *child = NULL;
453 fr_pair_t *vp;
455 uint8_t const *data;
456 size_t data_len;
457 eap_round_t *eap_round = eap_session->this_round;
458 rlm_eap_peap_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_eap_peap_t);
459
460 /*
461 * Just look at the buffer directly, without doing
462 * record_to_buff. This lets us avoid another data copy.
463 */
464 data_len = tls_session->clean_out.used;
465 tls_session->clean_out.used = 0;
466 data = tls_session->clean_out.data;
467
468 RDEBUG2("PEAP state %s", peap_state(t));
469
470 if ((t->status != PEAP_STATUS_TUNNEL_ESTABLISHED) && (eap_peap_verify(request, t, data, data_len) < 0)) {
471 REDEBUG("Tunneled data is invalid");
473 }
474
475 switch (t->status) {
477 /* FIXME: should be no data in the buffer here, check & assert? */
478
479 if (SSL_session_reused(tls_session->ssl)) {
480 RDEBUG2("Skipping Phase2 because of session resumption");
482 /* we're good, send success TLV */
484 if (eap_peap_success(request, eap_session, tls_session) < 0) {
485 rcode = RLM_MODULE_FAIL;
486 goto finish;
487 }
488
489 } else {
490 /* send an identity request */
493 if (eap_peap_identity(request, eap_session, tls_session) < 0) {
494 rcode = RLM_MODULE_FAIL;
495 goto finish;
496 }
497 }
498 rcode = RLM_MODULE_HANDLED;
499 goto finish;
500
502 /* we're expecting an identity response */
503 if (!data_len || (data[0] != FR_EAP_METHOD_IDENTITY)) {
504 REDEBUG("Expected EAP-Identity, got something else");
505 rcode = RLM_MODULE_REJECT;
506 goto finish;
507 }
508
509 /*
510 * Save it for later.
511 */
513 t->username->vp_tainted = true;
514
515 fr_pair_value_bstrndup(t->username, (char const *)data + 1, data_len - 1, true);
516
517 RDEBUG2("Got inner identity \"%pV\"", &t->username->data);
519 break;
520
521 /*
522 * If we authenticated the user, then it's OK.
523 */
525 if (eap_peap_check_tlv(request, data, data_len)) {
526 RDEBUG2("Success");
527 rcode = RLM_MODULE_OK;
528 goto finish;
529 }
530
531 /*
532 * Otherwise, the client rejected the session
533 * resumption. If the session is being re-used,
534 * we need to do a full authentication.
535 *
536 * We do this by sending an EAP-Identity request
537 * inside of the PEAP tunnel.
538 */
540 RDEBUG2("Client rejected session resumption. Re-starting full authentication");
541
542 /*
543 * Mark session resumption status.
544 */
547
548 if (eap_peap_identity(request, eap_session, tls_session) < 0) {
549 rcode = RLM_MODULE_FAIL;
550 goto finish;
551 }
552 rcode = RLM_MODULE_HANDLED;
553 goto finish;
554 }
555
556 REDEBUG("Sent a success, but received something weird in return");
557 rcode = RLM_MODULE_REJECT;
558 goto finish;
559
560 /*
561 * Supplicant ACKs our failure.
562 */
564 RINDENT();
565 REDEBUG("The users session was previously rejected: returning reject (again.)");
566 RIDEBUG("This means you need to read the PREVIOUS messages in the debug output");
567 RIDEBUG("to find out the reason why the user was rejected");
568 RIDEBUG("Look for \"reject\" or \"fail\". Those earlier messages will tell you");
569 RIDEBUG("what went wrong, and how to fix the problem");
570 REXDENT();
571
573
575 RDEBUG2("In state machine in phase2 init?");
576 break;
577
579 break;
580
581 default:
582 REDEBUG("Unhandled state in peap");
583 rcode = RLM_MODULE_REJECT;
584 goto finish;
585 }
586
587 MEM(child = unlang_subrequest_alloc(request, request->proto_dict));
588 fr_assert(fr_pair_list_empty(&child->request_pairs));
589
590 switch (t->status) {
591 /*
592 * If we're in PHASE2_INIT, the phase2 method hasn't been
593 * sent an Identity packet yet; do so from the stored
594 * username and this will kick off the phase2 eap method
595 */
597 {
598 size_t len;
599 uint8_t *q;
600
602
603 len = t->username->vp_length + EAP_HEADER_LEN + 1;
605
606 MEM(vp = fr_pair_afrom_da(child->request_ctx, attr_eap_message));
607 MEM(fr_pair_value_mem_alloc(vp, &q, len, false) == 0);
609 q[1] = eap_round->response->id;
610 q[2] = (len >> 8) & 0xff;
611 q[3] = len & 0xff;
613 memcpy(q + EAP_HEADER_LEN + 1,
614 t->username->vp_strvalue, t->username->vp_length);
615 fr_pair_append(&child->request_pairs, vp);
616 }
617 break;
618
620 eap_peap_inner_to_pairs(child->request_ctx, &child->request_pairs,
621 eap_round, data, data_len);
622 if (fr_pair_list_empty(&child->request_pairs)) {
623 TALLOC_FREE(child);
624 RDEBUG2("Unable to convert tunneled EAP packet to internal server data structures");
625 rcode = RLM_MODULE_REJECT;
626 goto finish;
627 }
628 break;
629
630 default:
631 REDEBUG("Invalid state change in PEAP");
632 rcode = RLM_MODULE_REJECT;
633 goto finish;
634 }
635
636 RDEBUG2("Got tunneled request");
637 log_request_pair_list(L_DBG_LVL_2, request, NULL, &child->request_pairs, NULL);
638
639 /*
640 * Update other items in the request_t data structure.
641 */
642 if (!t->username) {
643 /*
644 * There's no User-Name in the tunneled session,
645 * so we add one here, by pulling it out of the
646 * EAP-Identity packet.
647 */
648 if ((data[0] == FR_EAP_METHOD_IDENTITY) && (data_len > 1)) {
650 fr_assert(t->username != NULL);
651 t->username->vp_tainted = true;
652
653 fr_pair_value_bstrndup(t->username, (char const *)data + 1, data_len - 1, true);
654
655 RDEBUG2("Got tunneled identity of %pV", &t->username->data);
656 }
657 } /* else there WAS a t->username */
658
659 if (t->username) {
660 MEM(vp = fr_pair_copy(child->request_ctx, t->username));
661 fr_pair_append(&child->request_pairs, vp);
662 RDEBUG2("Setting request.User-Name from tunneled (inner) identity \"%s\"",
663 vp->vp_strvalue);
664 } else {
665 RDEBUG2("No tunnel username (SSL resumption?)");
666 }
667
668 /*
669 * Set the child up for execution. This represents
670 * a pseudo protocol inside of PEAPs inner EAP method.
671 */
672 if (unlang_subrequest_child_push(&eap_session->submodule_result, child,
673 child,
674 false, UNLANG_SUB_FRAME) < 0) goto finish;
675
676 /*
677 * Setup a function in thie child to process the
678 * result of the subrequest.
679 */
681 child,
682 NULL,
683 /*
684 * Run in the child after the virtual sever executes.
685 * This sets the rcode for the subrequest, which is
686 * written to eap_session->submodule_result.
687 */
689 NULL, 0,
690 UNLANG_SUB_FRAME, eap_session) != UNLANG_ACTION_PUSHED_CHILD) goto finish;
691
692 /*
693 * Run inner tunnel in the context of the child
694 */
695 if (unlikely(eap_virtual_server(child, eap_session, inst->virtual_server) == UNLANG_ACTION_FAIL)) {
696 rcode = RLM_MODULE_FAIL;
697 goto finish;
698 }
699
700 /*
701 * We now yield to the subrequest. unlang_subrequest_child_push
702 * pushed a new frame in the context of the parent which'll start
703 * the subrequest.
704 */
706
707finish:
708 if (child) {
709 /*
710 * We can't just free the child, we need to detach it
711 * and then let the interpreter to unwind and eventually
712 * free the request.
713 */
714 request_detach(child);
716 }
717
718 RETURN_UNLANG_RCODE(rcode);
719}
720
721/*
722 * Allocate the PEAP per-session data
723 */
724static peap_tunnel_t *peap_alloc(TALLOC_CTX *ctx)
725{
726 peap_tunnel_t *t;
727
728 t = talloc_zero(ctx, peap_tunnel_t);
730
731 return t;
732}
733
734/*
735 * Construct the reply appropriately based on the rcode from PEAP processing.
736 */
738{
739 eap_session_t *eap_session = talloc_get_type_abort(mctx->rctx, eap_session_t);
740 eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
741 fr_tls_session_t *tls_session = eap_tls_session->tls_session;
742
743 RDEBUG3("Tunneled request complete");
744
745 switch (eap_session->submodule_result.rcode) {
747 eap_tls_fail(request, eap_session);
748 break;
749
751 eap_tls_request(request, eap_session);
752 break;
753
754 case RLM_MODULE_OK:
755 {
756 eap_tls_prf_label_t prf_label;
757
758 eap_crypto_prf_label_init(&prf_label, eap_session,
759 "client EAP encryption",
760 sizeof("client EAP encryption") - 1);
761
762 /*
763 * Success: Automatically return MPPE keys.
764 */
765 if (eap_tls_success(request, eap_session, &prf_label) < 0) RETURN_UNLANG_FAIL;
766 p_result->rcode = RLM_MODULE_OK;
767
768 /*
769 * Write the session to the session cache
770 *
771 * We do this here (instead of relying on OpenSSL to call the
772 * session caching callback), because we only want to write
773 * session data to the cache if all phases were successful.
774 *
775 * If we wrote out the cache data earlier, and the server
776 * exited whilst the session was in progress, the supplicant
777 * could resume the session (and get access) even if phase2
778 * never completed.
779 */
780 return fr_tls_cache_pending_push(request, tls_session);
781 }
782
783 /*
784 * No response packet, MUST be proxying it.
785 * The main EAP module will take care of discovering
786 * that the request now has a "proxy" packet, and
787 * will proxy it, rather than returning an EAP packet.
788 */
790 break;
791
792 default:
793 eap_tls_fail(request, eap_session);
794 break;
795 }
796
798}
799
801{
802 eap_session_t *eap_session = talloc_get_type_abort(mctx->rctx, eap_session_t);
803 eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
804 fr_tls_session_t *tls_session = eap_tls_session->tls_session;
805 peap_tunnel_t *peap = talloc_get_type_abort(tls_session->opaque, peap_tunnel_t);
806
807 if ((eap_tls_session->state == EAP_TLS_INVALID) || (eap_tls_session->state == EAP_TLS_FAIL)) {
808 REDEBUG("[eap-tls process] = %s", fr_table_str_by_value(eap_tls_status_table, eap_tls_session->state, "<INVALID>"));
809 } else {
810 RDEBUG2("[eap-tls process] = %s", fr_table_str_by_value(eap_tls_status_table, eap_tls_session->state, "<INVALID>"));
811 }
812
813 switch (eap_tls_session->state) {
814 /*
815 * EAP-TLS handshake was successful, tell the
816 * client to keep talking.
817 *
818 * If this was EAP-TLS, we would just return
819 * an EAP-TLS-Success packet here.
820 */
823 break;
824
825 /*
826 * The TLS code is still working on the TLS
827 * exchange, and it's a valid TLS request.
828 * do nothing.
829 */
830 case EAP_TLS_HANDLED:
831 /*
832 * FIXME: If the SSL session is established, grab the state
833 * and EAP id from the inner tunnel, and update it with
834 * the expected EAP id!
835 */
837
838 /*
839 * Handshake is done, proceed with decoding tunneled
840 * data.
841 */
843 /*
844 * TLSv1.3 makes application data immediately
845 * available when the handshake is finished.
846 */
847 if (SSL_is_init_finished(tls_session->ssl) && (peap->status == PEAP_STATUS_INVALID)) {
849 }
850 break;
851
852 /*
853 * Anything else: fail.
854 */
855 default:
857 }
858
859 /*
860 * Session is established, proceed with decoding
861 * tunneled data.
862 */
863 RDEBUG2("Session established. Decoding tunneled data");
864
865 /*
866 * We may need PEAP data associated with the session, so
867 * allocate it here, if it wasn't already alloacted.
868 */
869 if (!tls_session->opaque) tls_session->opaque = peap_alloc(tls_session);
870
871 /*
872 * Setup the resume point to prepare the correct reply based on
873 * the rcode coming back from PEAP processing.
874 */
875 (void) unlang_module_yield(request, process_rcode, NULL, 0, eap_session);
876
877 /*
878 * Process the PEAP portion of the request.
879 */
880 return eap_peap_process(&eap_session->submodule_result, mctx, request, eap_session, tls_session);
881}
882
883/*
884 * Do authentication, by letting EAP-TLS do most of the work.
885 */
887 request_t *request)
888{
889 eap_session_t *eap_session = eap_session_get(request->parent);
890
891 /*
892 * Setup the resumption frame to process the result
893 */
894 (void)unlang_module_yield(request, mod_handshake_resume, NULL, 0, eap_session);
895
896 /*
897 * Process TLS layer until done.
898 */
899 return eap_tls_process(request, eap_session);
900}
901
903{
904 rlm_eap_peap_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_eap_peap_t);
905 rlm_eap_peap_thread_t *t = talloc_get_type_abort(mctx->thread, rlm_eap_peap_thread_t);
906 eap_session_t *eap_session = eap_session_get(request->parent);
907 eap_tls_session_t *eap_tls_session;
908 fr_tls_session_t *tls_session;
909
910 fr_pair_t *vp;
911 bool client_cert;
912
913 /*
914 * EAP-TLS-Require-Client-Cert attribute will override
915 * the require_client_cert configuration option.
916 */
917 vp = fr_pair_find_by_da(&request->control_pairs, NULL, attr_eap_tls_require_client_cert);
918 if (vp) {
919 client_cert = vp->vp_uint32 ? true : false;
920 } else {
921 client_cert = inst->req_client_cert;
922 }
923
924 eap_session->opaque = eap_tls_session = eap_tls_session_init(request, eap_session, t->ssl_ctx, client_cert);
925 if (!eap_tls_session) RETURN_UNLANG_FAIL;
926
927 tls_session = eap_tls_session->tls_session;
928
929 /*
930 * As it is a poorly designed protocol, PEAP uses
931 * bits in the TLS header to indicate PEAP
932 * version numbers. For now, we only support
933 * PEAP version 0, so it doesn't matter too much.
934 * However, if we support later versions of PEAP,
935 * we will need this flag to indicate which
936 * version we're currently dealing with.
937 */
938 eap_tls_session->base_flags = 0x00;
939
940 /*
941 * PEAP version 0 requires 'include_length = no',
942 * so rather than hoping the user figures it out,
943 * we force it here.
944 */
945 eap_tls_session->include_length = false;
946
947 /*
948 * TLS session initialization is over. Now handle TLS
949 * related handshaking or application data.
950 */
951 if (eap_tls_start(request, eap_session) < 0) {
952 talloc_free(eap_tls_session);
954 }
955
956 /*
957 * Session resumption requires the storage of data, so
958 * allocate it if it doesn't already exist.
959 */
960 tls_session->opaque = peap_alloc(tls_session);
961
962 eap_session->process = mod_handshake_process;
963
965}
966
967/*
968 * Send an initial eap-tls request to the peer, using the libeap functions.
969 */
971{
972 rlm_eap_peap_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_eap_peap_t);
973 eap_session_t *eap_session = eap_session_get(request->parent);
974
975 eap_session->tls = true;
976
977 (void) unlang_module_yield(request, mod_session_init_resume, NULL, 0, NULL);
978
979 if (inst->tls_conf->new_session) return fr_tls_new_session_push(request, inst->tls_conf);
980
982}
983
985{
986 rlm_eap_peap_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_eap_peap_t);
987 rlm_eap_peap_thread_t *t = talloc_get_type_abort(mctx->thread, rlm_eap_peap_thread_t);
988
989 t->ssl_ctx = fr_tls_ctx_alloc(inst->tls_conf, false);
990 if (!t->ssl_ctx) return -1;
991
992 return 0;
993}
994
996{
997 rlm_eap_peap_thread_t *t = talloc_get_type_abort(mctx->thread, rlm_eap_peap_thread_t);
998
999 if (likely(t->ssl_ctx != NULL)) SSL_CTX_free(t->ssl_ctx);
1000 t->ssl_ctx = NULL;
1001
1002 return 0;
1003}
1004
1005/*
1006 * Attach the module.
1007 */
1008static int mod_instantiate(module_inst_ctx_t const *mctx)
1009{
1010 rlm_eap_peap_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_eap_peap_t);
1011 CONF_SECTION *conf = mctx->mi->conf;
1012
1013 fr_assert(inst->virtual_server);
1014
1015 inst->server_cs = virtual_server_cs(inst->virtual_server);
1016
1017 /*
1018 * Read tls configuration, either from group given by 'tls'
1019 * option, or from the eap-tls configuration.
1020 */
1021 inst->tls_conf = eap_tls_conf_parse(conf);
1022 if (!inst->tls_conf) {
1023 cf_log_err(conf, "Failed initializing SSL context");
1024 return -1;
1025 }
1026
1027 return 0;
1028}
1029
1030/*
1031 * The module name should be the only globally exported symbol.
1032 * That is, everything else should be 'static'.
1033 */
1036 .common = {
1037 .magic = MODULE_MAGIC_INIT,
1038 .name = "eap_peap",
1039 .inst_size = sizeof(rlm_eap_peap_t),
1041 .instantiate = mod_instantiate,
1042
1043 .thread_inst_size = sizeof(rlm_eap_peap_thread_t),
1044 .thread_instantiate = mod_thread_instantiate,
1045 .thread_detach = mod_thread_detach,
1046 },
1047 .provides = { FR_EAP_METHOD_PEAP },
1048 .session_init = mod_session_init, /* Initialise a new EAP session */
1049};
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition action.h:35
@ UNLANG_ACTION_PUSHED_CHILD
unlang_t pushed a new child onto the stack, execute it instead of continuing.
Definition action.h:39
@ UNLANG_ACTION_FAIL
Encountered an unexpected error.
Definition action.h:36
@ UNLANG_ACTION_CALCULATE_RESULT
Calculate a new section rlm_rcode_t value.
Definition action.h:37
#define RCSID(id)
Definition build.h:560
#define unlikely(_x)
Definition build.h:455
#define UNUSED
Definition build.h:384
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:669
cf_parse_t func
Override default parsing behaviour for the specified type with a custom parsing function.
Definition cf_parse.h:623
#define FR_CONF_DEPRECATED(_name, _struct, _field)
conf_parser_t entry which raises an error if a matching CONF_PAIR is found
Definition cf_parse.h:409
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition cf_parse.h:280
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
Definition cf_parse.h:429
@ CONF_FLAG_NOT_EMPTY
CONF_PAIR is required to have a non zero length value.
Definition cf_parse.h:447
#define FR_CONF_OFFSET_TYPE_FLAGS(_name, _type, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Definition cf_parse.h:238
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:606
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:106
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:345
eap_packet_t * response
Packet we received from the peer.
Definition compose.h:48
uint8_t id
Definition compose.h:36
Contains a pair of request and response packets.
Definition compose.h:47
#define MEM(x)
Definition debug.h:38
@ 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
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition dict.h:292
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition dict.h:305
#define DICT_AUTOLOAD_TERMINATOR
Definition dict.h:311
Specifies an attribute which must be present for the module to function.
Definition dict.h:291
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition dict.h:304
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition dl_module.h:63
char const * eap_type2name(eap_type_t method)
Return an EAP-name for a particular type.
Definition types.c:54
uint8_t data[]
Definition types.h:125
uint8_t id
Definition types.h:133
@ FR_EAP_CODE_RESPONSE
Definition types.h:38
@ FR_EAP_CODE_REQUEST
Definition types.h:37
uint8_t code
Definition types.h:132
uint8_t length[2]
Definition types.h:134
enum eap_type eap_type_t
uint8_t code
Definition types.h:122
#define EAP_HEADER_LEN
Definition types.h:34
@ FR_EAP_METHOD_MSCHAPV2
Definition types.h:71
@ FR_EAP_METHOD_IDENTITY
Definition types.h:46
@ FR_EAP_METHOD_PEAP
Definition types.h:70
uint8_t data[1]
Definition types.h:135
When we need to create a base EAP packet.
Definition types.h:131
Structure to represent packet format of eap on wire
Definition types.h:121
#define unlang_function_push_with_result(_result_p, _request, _func, _repeat, _signal, _sigmask, _top_frame, _uctx)
Push a generic function onto the unlang stack that produces a result.
Definition function.h:144
talloc_free(hp)
void unlang_interpret_signal(request_t *request, fr_signal_t action)
Send a signal (usually stop) to a request.
Definition interpret.c:1789
unlang_mod_action_t priority
The priority or action for that rcode.
Definition interpret.h:142
#define UNLANG_SUB_FRAME
Definition interpret.h:37
rlm_rcode_t rcode
The current rcode, from executing the instruction or merging the result from a frame.
Definition interpret.h:140
unlang_action_t eap_virtual_server(request_t *request, eap_session_t *eap_session, virtual_server_t *virtual_server)
Run a subrequest through a virtual server.
Definition base.c:385
void eap_crypto_prf_label_init(eap_tls_prf_label_t *prf_label, eap_session_t *eap_session, char const *keying_prf_label, size_t keying_prf_label_len)
Initialize the PRF label fields.
Definition crypto.c:48
static eap_session_t * eap_session_get(request_t *request)
Definition session.h:85
void * opaque
Opaque data used by EAP methods.
Definition session.h:63
bool tls
Whether EAP method uses TLS.
Definition session.h:71
module_method_t process
Callback that should be used to process the next round.
Definition session.h:65
unlang_result_t submodule_result
Result of last submodule call.
Definition session.h:47
eap_round_t * this_round
The EAP response we're processing, and the EAP request we're building.
Definition session.h:60
Tracks the progress of a single session of any EAP method.
Definition session.h:41
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:828
#define REXDENT()
Exdent (unindent) R* messages by one level.
Definition log.h:460
#define RDEBUG3(fmt,...)
Definition log.h:360
#define REDEBUG2(fmt,...)
Definition log.h:389
#define RINDENT()
Indent R* messages by one level.
Definition log.h:447
@ L_DBG_LVL_2
2nd highest priority debug messages (-xx | -X).
Definition log.h:68
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_VOID
User data.
@ FR_TYPE_OCTETS
Raw octets.
unsigned char uint8_t
@ MOD_PRIORITY_MAX
Definition mod_action.h:61
module_instance_t const * mi
Instance of the module being instantiated.
Definition module_ctx.h:42
void * thread
Thread specific instance data.
Definition module_ctx.h:43
void * rctx
Resume ctx that a module previously set.
Definition module_ctx.h:45
void * thread
Thread instance data.
Definition module_ctx.h:67
module_instance_t const * mi
Instance of the module being instantiated.
Definition module_ctx.h:64
module_instance_t * mi
Instance of the module being instantiated.
Definition module_ctx.h:51
Temporary structure to hold arguments for module calls.
Definition module_ctx.h:41
Temporary structure to hold arguments for instantiation calls.
Definition module_ctx.h:50
Temporary structure to hold arguments for thread_instantiation calls.
Definition module_ctx.h:63
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:2416
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:2962
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:707
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:1352
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:290
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:2812
fr_pair_t * fr_pair_copy(TALLOC_CTX *ctx, fr_pair_t const *vp)
Copy a single valuepair.
Definition pair.c:503
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:2911
static const conf_parser_t config[]
Definition base.c:162
char const * fr_radius_packet_name[FR_RADIUS_CODE_MAX]
Definition base.c:115
#define fr_assert(_expr)
Definition rad_assert.h:37
#define REDEBUG(fmt,...)
#define RDEBUG_ENABLED2()
#define RDEBUG2(fmt,...)
#define FR_RADIUS_PACKET_CODE_VALID(_x)
Definition radius.h:51
static rs_t * conf
Definition radsniff.c:52
#define RIDEBUG(fmt,...)
Definition radsniff.h:65
#define RETURN_UNLANG_HANDLED
Definition rcode.h:65
#define RETURN_UNLANG_RCODE(_rcode)
Definition rcode.h:61
#define RETURN_UNLANG_FAIL
Definition rcode.h:63
#define RETURN_UNLANG_REJECT
Definition rcode.h:62
rlm_rcode_t
Return codes indicating the result of the module call.
Definition rcode.h:44
@ RLM_MODULE_OK
The module is OK, continue.
Definition rcode.h:49
@ RLM_MODULE_FAIL
Module failed, don't reply.
Definition rcode.h:48
@ RLM_MODULE_REJECT
Immediately reject the request.
Definition rcode.h:47
@ RLM_MODULE_UPDATED
OK (pairs modified).
Definition rcode.h:55
@ RLM_MODULE_HANDLED
The module handled the request, so stop.
Definition rcode.h:50
int request_detach(request_t *child)
Unlink a subrequest from its parent.
Definition request.c:544
static unlang_action_t mod_handshake_process(UNUSED unlang_result_t *p_result, UNUSED module_ctx_t const *mctx, request_t *request)
static unlang_action_t mod_handshake_resume(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
bool copy_request_to_tunnel
Use SOME of the request attributes from outside of the tunneled session in the tunneled request.
#define EAP_TLV_FAILURE
peap_status
@ PEAP_STATUS_PHASE2_INIT
@ PEAP_STATUS_TUNNEL_ESTABLISHED
@ PEAP_STATUS_PHASE2
@ PEAP_STATUS_INNER_IDENTITY_REQ_SENT
@ PEAP_STATUS_SENT_TLV_SUCCESS
@ PEAP_STATUS_SENT_TLV_FAILURE
@ PEAP_STATUS_INVALID
static fr_dict_attr_t const * attr_eap_message
peap_resumption
@ PEAP_RESUMPTION_YES
@ PEAP_RESUMPTION_NO
@ PEAP_RESUMPTION_MAYBE
static peap_tunnel_t * peap_alloc(TALLOC_CTX *ctx)
virtual_server_t * virtual_server
Virtual server for inner tunnel session.
static fr_dict_t const * dict_freeradius
static fr_dict_attr_t const * attr_eap_tls_require_client_cert
static int eap_peap_success(request_t *request, eap_session_t *eap_session, fr_tls_session_t *tls_session)
SSL_CTX * ssl_ctx
Thread local SSL_CTX.
fr_dict_attr_autoload_t rlm_eap_peap_dict_attr[]
fr_dict_autoload_t rlm_eap_peap_dict[]
static unlang_action_t process_reply(unlang_result_t *p_result, request_t *request, void *uctx)
static unlang_action_t mod_session_init_resume(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
static fr_dict_t const * dict_radius
static int eap_peap_identity(request_t *request, eap_session_t *eap_session, fr_tls_session_t *tls_session)
#define FR_PEAP_EXTENSIONS_TYPE
static fr_dict_attr_t const * attr_auth_type
static unlang_action_t eap_peap_process(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request, eap_session_t *eap_session, fr_tls_session_t *tls_session)
char const * tls_conf_name
TLS configuration.
fr_tls_conf_t * tls_conf
static int eap_peap_check_tlv(request_t *request, uint8_t const *data, size_t data_len)
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)
peap_status status
bool home_access_accept
peap_resumption session_resumption_state
bool req_client_cert
Do we do require a client cert?
rlm_eap_submodule_t rlm_eap_peap
bool use_tunneled_reply
Use the reply attributes from the tunneled session in the non-tunneled reply to the client.
static int mod_thread_instantiate(module_thread_inst_ctx_t const *mctx)
static int eap_peap_inner_from_pairs(request_t *request, fr_tls_session_t *tls_session, fr_pair_list_t *vps)
static unlang_action_t process_rcode(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
static char const * peap_state(peap_tunnel_t *t)
#define EAP_TLV_SUCCESS
static fr_dict_attr_t const * attr_user_name
static conf_parser_t submodule_config[]
static int eap_peap_failure(request_t *request, eap_session_t *eap_session, fr_tls_session_t *tls_session)
static unlang_action_t mod_session_init(UNUSED unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
static int eap_peap_verify(request_t *request, peap_tunnel_t *peap_tunnel, uint8_t const *data, size_t data_len)
static int mod_thread_detach(module_thread_inst_ctx_t const *mctx)
static int mod_instantiate(module_inst_ctx_t const *mctx)
fr_pair_t * username
CONF_SECTION * server_cs
#define EAP_TLV_ACK_RESULT
CONF_SECTION * conf
Module's instance configuration.
Definition module.h:351
size_t inst_size
Size of the module's instance data.
Definition module.h:212
void * data
Module's instance data.
Definition module.h:293
@ FR_SIGNAL_CANCEL
Request has been cancelled.
Definition signal.h:40
unlang_action_t unlang_module_yield(request_t *request, module_method_t resume, unlang_module_signal_t signal, fr_signal_t sigmask, void *rctx)
Yield a request back to the interpreter from within a module.
Definition module.c:431
eap_aka_sim_process_conf_t * inst
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
module_t common
Common fields provided by all modules.
Definition submodule.h:50
Interface exported by EAP submodules.
Definition submodule.h:49
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:302
int unlang_subrequest_child_push(unlang_result_t *p_result, request_t *child, void const *unique_session_ptr, bool free_child, bool top_frame)
Push a pre-existing child back onto the stack as a subrequest.
Definition subrequest.c:426
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
Definition table.h:804
int eap_tls_success(request_t *request, eap_session_t *eap_session, eap_tls_prf_label_t *prf_label)
Send an EAP-TLS success.
Definition tls.c:263
eap_tls_session_t * eap_tls_session_init(request_t *request, eap_session_t *eap_session, SSL_CTX *ssl_ctx, bool client_cert)
Create a new fr_tls_session_t associated with an eap_session_t.
Definition tls.c:1155
int eap_tls_start(request_t *request, eap_session_t *eap_session)
Send an initial EAP-TLS request to the peer.
Definition tls.c:238
int eap_tls_request(request_t *request, eap_session_t *eap_session)
Frames the OpenSSL data that needs to be sent to the client in an EAP-Request.
Definition tls.c:371
int eap_tls_fail(request_t *request, eap_session_t *eap_session)
Send an EAP-TLS failure.
Definition tls.c:321
USES_APPLE_DEPRECATED_API fr_table_num_ordered_t const eap_tls_status_table[]
Definition tls.c:79
fr_tls_conf_t * eap_tls_conf_parse(CONF_SECTION *cs)
Parse TLS configuration.
Definition tls.c:1287
unlang_action_t eap_tls_process(request_t *request, eap_session_t *eap_session)
Process an EAP TLS request.
Definition tls.c:981
int base_flags
Some protocols use the reserved bits of the EAP-TLS flags (such as PEAP).
Definition tls.h:128
eap_tls_status_t state
The state of the EAP-TLS session.
Definition tls.h:123
@ EAP_TLS_INVALID
Invalid, don't reply.
Definition tls.h:87
@ EAP_TLS_HANDLED
TLS code has handled it.
Definition tls.h:90
@ EAP_TLS_RECORD_RECV_COMPLETE
Received final fragment of a record.
Definition tls.h:107
@ EAP_TLS_FAIL
Fail, send fail.
Definition tls.h:89
@ EAP_TLS_ESTABLISHED
Session established, send success (or start phase2).
Definition tls.h:88
fr_tls_session_t * tls_session
TLS session used to authenticate peer or tunnel sensitive data.
Definition tls.h:125
bool include_length
A flag to include length in every TLS Data/Alert packet.
Definition tls.h:134
Tracks the state of an EAP-TLS session.
Definition tls.h:122
unsigned int code
Packet code (type).
Definition packet.h:61
bool fr_pair_list_empty(fr_pair_list_t const *list)
Is a valuepair list empty.
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:69
void fr_pair_list_free(fr_pair_list_t *list)
Free memory used by a valuepair list.
#define vp_length
Definition pair.h:117
fr_pair_t * fr_pair_list_head(fr_pair_list_t const *list)
Get the head of a valuepair list.
Definition pair_inline.c:42
static fr_slen_t parent
Definition pair.h:858
static fr_slen_t data
Definition value.h:1340
int virtual_server_cf_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
Wrapper for the config parser to allow pass1 resolution of virtual servers.
CONF_SECTION * virtual_server_cs(virtual_server_t const *vs)
Return the configuration section for a virtual server.
Additional validation rules for virtual server lookup.