The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
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: 667a2424d813336013f1f052e8e3d82409c1ed3e $
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: 667a2424d813336013f1f052e8e3d82409c1ed3e $")
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) {
383 RDEBUG2("Tunneled authentication was successful");
385 if (eap_peap_success(request, eap_session, tls_session) < 0) RETURN_UNLANG_FAIL;
387
389 RDEBUG2("Tunneled authentication was rejected");
391 if (eap_peap_failure(request, eap_session, tls_session) < 0) RETURN_UNLANG_FAIL;
393
395 RDEBUG2("Got tunneled Access-Challenge");
396
397 /*
398 * PEAP takes only EAP-Message attributes inside
399 * of the tunnel. Any Reply-Message in the
400 * Access-Challenge is ignored.
401 */
402 fr_pair_list_init(&vps);
403 MEM(fr_pair_list_copy_by_da(t, &vps, &request->reply_pairs, attr_eap_message, 0) >= 0);
404
405 /*
406 * Handle the ACK, by tunneling any necessary reply
407 * VP's back to the client.
408 */
409 if (!fr_pair_list_empty(&vps)) {
410 eap_peap_inner_from_pairs(parent, tls_session, &vps);
411 fr_pair_list_free(&vps);
412 }
414
415 default:
416 RDEBUG2("Unknown RADIUS packet type %d: rejecting tunneled user", reply->code);
418 }
419}
420
421
422static char const *peap_state(peap_tunnel_t *t)
423{
424 switch (t->status) {
426 return "TUNNEL ESTABLISHED";
427
429 return "WAITING FOR INNER IDENTITY";
430
432 return "send tlv success";
433
435 return "send tlv failure";
436
438 return "phase2_init";
439
441 return "phase2";
442
443 default:
444 break;
445 }
446 return "?";
447}
448
449/*
450 * Process the pseudo-EAP contents of the tunneled data.
451 */
453 eap_session_t *eap_session, fr_tls_session_t *tls_session)
454{
455 peap_tunnel_t *t = tls_session->opaque;
456 request_t *child = NULL;
457 fr_pair_t *vp;
459 uint8_t const *data;
460 size_t data_len;
461 eap_round_t *eap_round = eap_session->this_round;
462 rlm_eap_peap_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_eap_peap_t);
463
464 /*
465 * Just look at the buffer directly, without doing
466 * record_to_buff. This lets us avoid another data copy.
467 */
468 data_len = tls_session->clean_out.used;
469 tls_session->clean_out.used = 0;
470 data = tls_session->clean_out.data;
471
472 RDEBUG2("PEAP state %s", peap_state(t));
473
474 if ((t->status != PEAP_STATUS_TUNNEL_ESTABLISHED) && (eap_peap_verify(request, t, data, data_len) < 0)) {
475 REDEBUG("Tunneled data is invalid");
477 }
478
479 switch (t->status) {
481 /* FIXME: should be no data in the buffer here, check & assert? */
482
483 if (SSL_session_reused(tls_session->ssl)) {
484 RDEBUG2("Skipping Phase2 because of session resumption");
486 /* we're good, send success TLV */
488 if (eap_peap_success(request, eap_session, tls_session) < 0) {
489 rcode = RLM_MODULE_FAIL;
490 goto finish;
491 }
492
493 } else {
494 /* send an identity request */
497 if (eap_peap_identity(request, eap_session, tls_session) < 0) {
498 rcode = RLM_MODULE_FAIL;
499 goto finish;
500 }
501 }
502 rcode = RLM_MODULE_HANDLED;
503 goto finish;
504
506 /* we're expecting an identity response */
507 if (!data_len || (data[0] != FR_EAP_METHOD_IDENTITY)) {
508 REDEBUG("Expected EAP-Identity, got something else");
509 rcode = RLM_MODULE_REJECT;
510 goto finish;
511 }
512
513 /*
514 * Save it for later.
515 */
517 t->username->vp_tainted = true;
518
519 fr_pair_value_bstrndup(t->username, (char const *)data + 1, data_len - 1, true);
520
521 RDEBUG2("Got inner identity \"%pV\"", &t->username->data);
523 break;
524
525 /*
526 * If we authenticated the user, then it's OK.
527 */
529 if (eap_peap_check_tlv(request, data, data_len)) {
530 RDEBUG2("Success");
531 rcode = RLM_MODULE_OK;
532 goto finish;
533 }
534
535 /*
536 * Otherwise, the client rejected the session
537 * resumption. If the session is being re-used,
538 * we need to do a full authentication.
539 *
540 * We do this by sending an EAP-Identity request
541 * inside of the PEAP tunnel.
542 */
544 RDEBUG2("Client rejected session resumption. Re-starting full authentication");
545
546 /*
547 * Mark session resumption status.
548 */
551
552 if (eap_peap_identity(request, eap_session, tls_session) < 0) {
553 rcode = RLM_MODULE_FAIL;
554 goto finish;
555 }
556 rcode = RLM_MODULE_HANDLED;
557 goto finish;
558 }
559
560 REDEBUG("Sent a success, but received something weird in return");
561 rcode = RLM_MODULE_REJECT;
562 goto finish;
563
564 /*
565 * Supplicant ACKs our failure.
566 */
568 RINDENT();
569 REDEBUG("The users session was previously rejected: returning reject (again.)");
570 RIDEBUG("This means you need to read the PREVIOUS messages in the debug output");
571 RIDEBUG("to find out the reason why the user was rejected");
572 RIDEBUG("Look for \"reject\" or \"fail\". Those earlier messages will tell you");
573 RIDEBUG("what went wrong, and how to fix the problem");
574 REXDENT();
575
577
579 RDEBUG2("In state machine in phase2 init?");
580 break;
581
583 break;
584
585 default:
586 REDEBUG("Unhandled state in peap");
587 rcode = RLM_MODULE_REJECT;
588 goto finish;
589 }
590
591 MEM(child = unlang_subrequest_alloc(request, request->proto_dict));
592 fr_assert(fr_pair_list_empty(&child->request_pairs));
593
594 switch (t->status) {
595 /*
596 * If we're in PHASE2_INIT, the phase2 method hasn't been
597 * sent an Identity packet yet; do so from the stored
598 * username and this will kick off the phase2 eap method
599 */
601 {
602 size_t len;
603 uint8_t *q;
604
606
607 len = t->username->vp_length + EAP_HEADER_LEN + 1;
609
610 MEM(vp = fr_pair_afrom_da(child->request_ctx, attr_eap_message));
611 MEM(fr_pair_value_mem_alloc(vp, &q, len, false) == 0);
613 q[1] = eap_round->response->id;
614 q[2] = (len >> 8) & 0xff;
615 q[3] = len & 0xff;
617 memcpy(q + EAP_HEADER_LEN + 1,
618 t->username->vp_strvalue, t->username->vp_length);
619 fr_pair_append(&child->request_pairs, vp);
620 }
621 break;
622
624 eap_peap_inner_to_pairs(child->request_ctx, &child->request_pairs,
625 eap_round, data, data_len);
626 if (fr_pair_list_empty(&child->request_pairs)) {
627 TALLOC_FREE(child);
628 RDEBUG2("Unable to convert tunneled EAP packet to internal server data structures");
629 rcode = RLM_MODULE_REJECT;
630 goto finish;
631 }
632 break;
633
634 default:
635 REDEBUG("Invalid state change in PEAP");
636 rcode = RLM_MODULE_REJECT;
637 goto finish;
638 }
639
640 RDEBUG2("Got tunneled request");
641 log_request_pair_list(L_DBG_LVL_2, request, NULL, &child->request_pairs, NULL);
642
643 /*
644 * Update other items in the request_t data structure.
645 */
646 if (!t->username) {
647 /*
648 * There's no User-Name in the tunneled session,
649 * so we add one here, by pulling it out of the
650 * EAP-Identity packet.
651 */
652 if ((data[0] == FR_EAP_METHOD_IDENTITY) && (data_len > 1)) {
654 fr_assert(t->username != NULL);
655 t->username->vp_tainted = true;
656
657 fr_pair_value_bstrndup(t->username, (char const *)data + 1, data_len - 1, true);
658
659 RDEBUG2("Got tunneled identity of %pV", &t->username->data);
660 }
661 } /* else there WAS a t->username */
662
663 if (t->username) {
664 MEM(vp = fr_pair_copy(child->request_ctx, t->username));
665 fr_pair_append(&child->request_pairs, vp);
666 RDEBUG2("Setting request.User-Name from tunneled (inner) identity \"%s\"",
667 vp->vp_strvalue);
668 } else {
669 RDEBUG2("No tunnel username (SSL resumption?)");
670 }
671
672 /*
673 * Set the child up for execution. This represents
674 * a pseudo protocol inside of PEAPs inner EAP method.
675 */
676 if (unlang_subrequest_child_push(&eap_session->submodule_result, child,
677 child,
678 false, UNLANG_SUB_FRAME) < 0) goto finish;
679
680 /*
681 * Setup a function in thie child to process the
682 * result of the subrequest.
683 */
685 child,
686 NULL,
687 /*
688 * Run in the child after the virtual sever executes.
689 * This sets the rcode for the subrequest, which is
690 * written to eap_session->submodule_result.
691 */
693 NULL, 0,
694 UNLANG_SUB_FRAME, eap_session) != UNLANG_ACTION_PUSHED_CHILD) goto finish;
695
696 /*
697 * Run inner tunnel in the context of the child
698 */
699 if (unlikely(eap_virtual_server(child, eap_session, inst->virtual_server) == UNLANG_ACTION_FAIL)) {
700 rcode = RLM_MODULE_FAIL;
701 goto finish;
702 }
703
704 /*
705 * We now yield to the subrequest. unlang_subrequest_child_push
706 * pushed a new frame in the context of the parent which'll start
707 * the subrequest.
708 */
710
711finish:
712 if (child) {
713 /*
714 * We can't just free the child, we need to detach it
715 * and then let the interpreter to unwind and eventually
716 * free the request.
717 */
718 request_detach(child);
720 }
721
722 RETURN_UNLANG_RCODE(rcode);
723}
724
725/*
726 * Allocate the PEAP per-session data
727 */
728static peap_tunnel_t *peap_alloc(TALLOC_CTX *ctx)
729{
730 peap_tunnel_t *t;
731
732 t = talloc_zero(ctx, peap_tunnel_t);
734
735 return t;
736}
737
738/*
739 * Construct the reply appropriately based on the rcode from PEAP processing.
740 */
742{
743 eap_session_t *eap_session = talloc_get_type_abort(mctx->rctx, eap_session_t);
744 eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
745 fr_tls_session_t *tls_session = eap_tls_session->tls_session;
746
747 RDEBUG3("Tunneled request complete");
748
749 switch (eap_session->submodule_result.rcode) {
751 eap_tls_fail(request, eap_session);
752 break;
753
755 eap_tls_request(request, eap_session);
756 break;
757
758 case RLM_MODULE_OK:
759 {
760 eap_tls_prf_label_t prf_label;
761
762 eap_crypto_prf_label_init(&prf_label, eap_session,
763 "client EAP encryption",
764 sizeof("client EAP encryption") - 1);
765
766 /*
767 * Success: Automatically return MPPE keys.
768 */
769 if (eap_tls_success(request, eap_session, &prf_label) < 0) RETURN_UNLANG_FAIL;
770 p_result->rcode = RLM_MODULE_OK;
771
772 /*
773 * Write the session to the session cache
774 *
775 * We do this here (instead of relying on OpenSSL to call the
776 * session caching callback), because we only want to write
777 * session data to the cache if all phases were successful.
778 *
779 * If we wrote out the cache data earlier, and the server
780 * exited whilst the session was in progress, the supplicant
781 * could resume the session (and get access) even if phase2
782 * never completed.
783 */
784 return fr_tls_cache_pending_push(request, tls_session);
785 }
786
787 /*
788 * No response packet, MUST be proxying it.
789 * The main EAP module will take care of discovering
790 * that the request now has a "proxy" packet, and
791 * will proxy it, rather than returning an EAP packet.
792 */
794 break;
795
796 default:
797 eap_tls_fail(request, eap_session);
798 break;
799 }
800
802}
803
805{
806 eap_session_t *eap_session = talloc_get_type_abort(mctx->rctx, eap_session_t);
807 eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
808 fr_tls_session_t *tls_session = eap_tls_session->tls_session;
809 peap_tunnel_t *peap = talloc_get_type_abort(tls_session->opaque, peap_tunnel_t);
810
811 if ((eap_tls_session->state == EAP_TLS_INVALID) || (eap_tls_session->state == EAP_TLS_FAIL)) {
812 REDEBUG("[eap-tls process] = %s", fr_table_str_by_value(eap_tls_status_table, eap_tls_session->state, "<INVALID>"));
813 } else {
814 RDEBUG2("[eap-tls process] = %s", fr_table_str_by_value(eap_tls_status_table, eap_tls_session->state, "<INVALID>"));
815 }
816
817 switch (eap_tls_session->state) {
818 /*
819 * EAP-TLS handshake was successful, tell the
820 * client to keep talking.
821 *
822 * If this was EAP-TLS, we would just return
823 * an EAP-TLS-Success packet here.
824 */
827 break;
828
829 /*
830 * The TLS code is still working on the TLS
831 * exchange, and it's a valid TLS request.
832 * do nothing.
833 */
834 case EAP_TLS_HANDLED:
835 /*
836 * FIXME: If the SSL session is established, grab the state
837 * and EAP id from the inner tunnel, and update it with
838 * the expected EAP id!
839 */
841
842 /*
843 * Handshake is done, proceed with decoding tunneled
844 * data.
845 */
847 /*
848 * TLSv1.3 makes application data immediately
849 * available when the handshake is finished.
850 */
851 if (SSL_is_init_finished(tls_session->ssl) && (peap->status == PEAP_STATUS_INVALID)) {
853 }
854 break;
855
856 /*
857 * Anything else: fail.
858 */
859 default:
861 }
862
863 /*
864 * Session is established, proceed with decoding
865 * tunneled data.
866 */
867 RDEBUG2("Session established. Decoding tunneled data");
868
869 /*
870 * We may need PEAP data associated with the session, so
871 * allocate it here, if it wasn't already alloacted.
872 */
873 if (!tls_session->opaque) tls_session->opaque = peap_alloc(tls_session);
874
875 /*
876 * Setup the resume point to prepare the correct reply based on
877 * the rcode coming back from PEAP processing.
878 */
879 (void) unlang_module_yield(request, process_rcode, NULL, 0, eap_session);
880
881 /*
882 * Process the PEAP portion of the request.
883 */
884 return eap_peap_process(&eap_session->submodule_result, mctx, request, eap_session, tls_session);
885}
886
887/*
888 * Do authentication, by letting EAP-TLS do most of the work.
889 */
891 request_t *request)
892{
893 eap_session_t *eap_session = eap_session_get(request->parent);
894
895 /*
896 * Setup the resumption frame to process the result
897 */
898 (void)unlang_module_yield(request, mod_handshake_resume, NULL, 0, eap_session);
899
900 /*
901 * Process TLS layer until done.
902 */
903 return eap_tls_process(request, eap_session);
904}
905
907{
908 rlm_eap_peap_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_eap_peap_t);
909 rlm_eap_peap_thread_t *t = talloc_get_type_abort(mctx->thread, rlm_eap_peap_thread_t);
910 eap_session_t *eap_session = eap_session_get(request->parent);
911 eap_tls_session_t *eap_tls_session;
912 fr_tls_session_t *tls_session;
913
914 fr_pair_t *vp;
915 bool client_cert;
916
917 /*
918 * EAP-TLS-Require-Client-Cert attribute will override
919 * the require_client_cert configuration option.
920 */
921 vp = fr_pair_find_by_da(&request->control_pairs, NULL, attr_eap_tls_require_client_cert);
922 if (vp) {
923 client_cert = vp->vp_uint32 ? true : false;
924 } else {
925 client_cert = inst->req_client_cert;
926 }
927
928 eap_session->opaque = eap_tls_session = eap_tls_session_init(request, eap_session, t->ssl_ctx, client_cert);
929 if (!eap_tls_session) RETURN_UNLANG_FAIL;
930
931 tls_session = eap_tls_session->tls_session;
932
933 /*
934 * As it is a poorly designed protocol, PEAP uses
935 * bits in the TLS header to indicate PEAP
936 * version numbers. For now, we only support
937 * PEAP version 0, so it doesn't matter too much.
938 * However, if we support later versions of PEAP,
939 * we will need this flag to indicate which
940 * version we're currently dealing with.
941 */
942 eap_tls_session->base_flags = 0x00;
943
944 /*
945 * PEAP version 0 requires 'include_length = no',
946 * so rather than hoping the user figures it out,
947 * we force it here.
948 */
949 eap_tls_session->include_length = false;
950
951 /*
952 * TLS session initialization is over. Now handle TLS
953 * related handshaking or application data.
954 */
955 if (eap_tls_start(request, eap_session) < 0) {
956 talloc_free(eap_tls_session);
958 }
959
960 /*
961 * Session resumption requires the storage of data, so
962 * allocate it if it doesn't already exist.
963 */
964 tls_session->opaque = peap_alloc(tls_session);
965
966 eap_session->process = mod_handshake_process;
967
969}
970
971/*
972 * Send an initial eap-tls request to the peer, using the libeap functions.
973 */
975{
976 rlm_eap_peap_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_eap_peap_t);
977 eap_session_t *eap_session = eap_session_get(request->parent);
978
979 eap_session->tls = true;
980
981 (void) unlang_module_yield(request, mod_session_init_resume, NULL, 0, NULL);
982
983 if (inst->tls_conf->new_session) return fr_tls_new_session_push(request, inst->tls_conf);
984
986}
987
989{
990 rlm_eap_peap_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_eap_peap_t);
991 rlm_eap_peap_thread_t *t = talloc_get_type_abort(mctx->thread, rlm_eap_peap_thread_t);
992
993 t->ssl_ctx = fr_tls_ctx_alloc(inst->tls_conf, false);
994 if (!t->ssl_ctx) return -1;
995
996 return 0;
997}
998
1000{
1001 rlm_eap_peap_thread_t *t = talloc_get_type_abort(mctx->thread, rlm_eap_peap_thread_t);
1002
1003 if (likely(t->ssl_ctx != NULL)) SSL_CTX_free(t->ssl_ctx);
1004 t->ssl_ctx = NULL;
1005
1006 return 0;
1007}
1008
1009/*
1010 * Attach the module.
1011 */
1012static int mod_instantiate(module_inst_ctx_t const *mctx)
1013{
1014 rlm_eap_peap_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_eap_peap_t);
1015 CONF_SECTION *conf = mctx->mi->conf;
1016
1017 fr_assert(inst->virtual_server);
1018
1019 inst->server_cs = virtual_server_cs(inst->virtual_server);
1020
1021 /*
1022 * Read tls configuration, either from group given by 'tls'
1023 * option, or from the eap-tls configuration.
1024 */
1025 inst->tls_conf = eap_tls_conf_parse(conf);
1026 if (!inst->tls_conf) {
1027 cf_log_err(conf, "Failed initializing SSL context");
1028 return -1;
1029 }
1030
1031 return 0;
1032}
1033
1034/*
1035 * The module name should be the only globally exported symbol.
1036 * That is, everything else should be 'static'.
1037 */
1040 .common = {
1041 .magic = MODULE_MAGIC_INIT,
1042 .name = "eap_peap",
1043 .inst_size = sizeof(rlm_eap_peap_t),
1045 .instantiate = mod_instantiate,
1046
1047 .thread_inst_size = sizeof(rlm_eap_peap_thread_t),
1048 .thread_instantiate = mod_thread_instantiate,
1049 .thread_detach = mod_thread_detach,
1050 },
1051 .provides = { FR_EAP_METHOD_PEAP },
1052 .session_init = mod_session_init, /* Initialise a new EAP session */
1053};
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:506
#define unlikely(_x)
Definition build.h:402
#define UNUSED
Definition build.h:336
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:657
cf_parse_t func
Override default parsing behaviour for the specified type with a custom parsing function.
Definition cf_parse.h:611
#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:594
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:101
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:285
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:46
@ 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
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
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:1417
unlang_mod_action_t priority
The priority or action for that rcode.
Definition interpret.h:136
#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:134
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:387
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:831
#define REXDENT()
Exdent (unindent) R* messages by one level.
Definition log.h:455
#define RDEBUG3(fmt,...)
Definition log.h:355
#define RINDENT()
Indent R* messages by one level.
Definition log.h:442
@ 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:163
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:52
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:542
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:772
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.