The FreeRADIUS server $Id: a4e7f8c94e8038b7627bcf52356b7ed15955c1d7 $
Loading...
Searching...
No Matches
tls.c
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or (at
5 * your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: 9b3b7894540917f75cd3571469ee4cad8acdb421 $
19 * @file lib/eap/tls.c
20 * @brief Implements the EAP part of EAP-TLS
21 *
22 * RFC 2716 Section 4.2. PPP EAP TLS Request Packet
23 @verbatim
24 0 1 2 3
25 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
26 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
27 | Code | Identifier | Length |
28 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
29 | Type | Flags | TLS Message Length
30 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
31 | TLS Message Length | TLS Data...
32 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
33 @endverbatim
34 *
35 * Structure of an EAP-TLS packet
36 *
37 @verbatim
38 code = EAP-code
39 id = EAP-id
40 length = code + id + length + flags + tlsdata
41 = 1 + 1 + 2 + 1 + X
42 length = EAP-length - 1(EAP-Type = 1 octet)
43 flags = EAP-typedata[0] (1 octet)
44 data_len = EAP-typedata[1-4] (4 octets), if L flag set
45 = length - 5(code+id+length+flags), otherwise
46 data = EAP-typedata[5-n], if L flag set
47 = EAP-typedata[1-n], otherwise
48 packet = EAP-typedata (complete typedata)
49 @endverbatim
50 *
51 * The S flag is set only within the EAP-TLS start message sent from the EAP
52 * server to the peer.
53 *
54 * Similarly, when the EAP server receives an EAP-Response with the M bit set,
55 * it MUST respond with an EAP-Request with EAP-Type = EAP-TLS and no data.
56 * This serves as a fragment ACK. The EAP peer MUST wait.
57 *
58 * The Length field is two octets and indicates the length of the EAP
59 * packet including the Code, Identifier, Length, Type, and TLS data
60 * fields.
61 *
62 * The TLS Message Length field is four octets and indicates the
63 * complete reassembled length of the TLS record fragment.
64 *
65 * @copyright 2001 hereUare Communications, Inc. (raghud@hereuare.com)
66 * @copyright 2003 Alan DeKok (aland@freeradius.org)
67 * @copyright 2006,2015 The FreeRADIUS server project
68 * @copyright 2015 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
69 */
70
71RCSID("$Id: 9b3b7894540917f75cd3571469ee4cad8acdb421 $")
72USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */
73
74#include <freeradius-devel/unlang/action.h>
75#include <freeradius-devel/unlang/function.h>
76#include <freeradius-devel/server/pair.h>
77#include "tls.h"
78#include "attrs.h"
79
81 { L("invalid"), EAP_TLS_INVALID },
82 { L("established"), EAP_TLS_ESTABLISHED },
83 { L("fail"), EAP_TLS_FAIL },
84 { L("handled"), EAP_TLS_HANDLED },
85
86 { L("start"), EAP_TLS_START_SEND },
87 { L("request"), EAP_TLS_RECORD_SEND },
88 { L("ack"), EAP_TLS_ACK_SEND },
89
90 { L("first"), EAP_TLS_RECORD_RECV_FIRST },
91 { L("more"), EAP_TLS_RECORD_RECV_MORE },
92 { L("complete"), EAP_TLS_RECORD_RECV_COMPLETE }
93};
95
96/** Convert the EAP-TLS reply packet into an EAP packet
97 *
98 * The EAP packet will be written to eap_round->request, with the original reply
99 * being untouched.
100 *
101 * @param[in] request The current subrequest.
102 * @param[in] eap_session to continue.
103 * @param[in] status What type of packet we're sending.
104 * @param[in] flags to set. This is checked to determine if
105 * we need to include a length field.
106 * @param[in] record The record buffer to read from. This
107 * most only be set for EAP_TLS_RECORD_SEND packets.
108 * @param[in] record_len the length of the record we're sending.
109 * @param[in] frag_len the length of the fragment we're sending.
110 * @return
111 * - 0 on success.
112 * - -1 on failure.
113 */
115 fr_dbuff_t *record, size_t record_len, size_t frag_len)
116{
117 eap_round_t *eap_round = eap_session->this_round;
118 uint8_t *p;
119 size_t len = 1; /* Flags */
120
121 fr_assert(request->parent); /* must be a subrequest */
122
123 /*
124 * First output the flags (for debugging)
125 */
126 RDEBUG3("Setting flags %c%c%c%c%c%c%c%c",
127 TLS_START(flags) ? 'S' : '-',
128 TLS_MORE_FRAGMENTS(flags) ? 'M' : '-',
129 TLS_LENGTH_INCLUDED(flags) ? 'L' : '-',
130 TLS_RESERVED0(flags) ? 'R' : '-',
131 TLS_RESERVED1(flags) ? 'R' : '-',
132 TLS_RESERVED2(flags) ? 'R' : '-',
133 TLS_RESERVED3(flags) ? 'R' : '-',
134 TLS_RESERVED4(flags) ? 'R' : '-');
135
136 /*
137 * Determine the length (sans header) of our EAP-TLS
138 * packet. The reason for not including the length is
139 * that the fields are the same as normal EAP messages.
140 */
141 switch (status) {
143 if (TLS_LENGTH_INCLUDED(flags)) len += TLS_HEADER_LENGTH_FIELD_LEN; /* TLS record length field */
144 if (record) len += frag_len;
145 break;
146
148 if (record_len != 0) len += frag_len;
149 break;
150
151 default:
152 break;
153 }
154
155 /*
156 * When the EAP server receives an EAP-Response with the
157 * M bit set, it MUST respond with an EAP-Request with
158 * EAP-Type = EAP-TLS and no data. This serves as a
159 * fragment ACK. The EAP peer MUST wait until it receives
160 * the EAP-Request before sending another fragment.
161 *
162 * In order to prevent errors in the processing of
163 * fragments, the EAP server MUST use increment the
164 * Identifier value for each fragment ACK contained
165 * within an EAP-Request, and the peer MUST include this
166 * Identifier value in the subsequent fragment contained
167 * within an EAP-Reponse.
168 */
169 eap_round->request->type.data = p = talloc_array(eap_round->request, uint8_t, len);
170 if (!p) return -1;
171 eap_round->request->type.length = len;
172
173 *p++ = flags;
174
175 if (TLS_LENGTH_INCLUDED(flags)) {
176 uint32_t net_record_len;
177
178 /*
179 * If we need to add the length field,
180 * convert the total record length to
181 * network byte order and copy it in at the
182 * start of the packet.
183 */
184 net_record_len = htonl(record_len);
185 memcpy(p, &net_record_len, sizeof(net_record_len));
186 p += sizeof(net_record_len);
187 }
188
189 /*
190 * Limit the dbuff call to "frag_len". If we ask for
191 * more, then the dbuff code will try to extend the
192 * buffer, and we don't want that.
193 */
194 if (record) (void) fr_dbuff_out_memcpy(p, record, frag_len);
195
196 switch (status) {
197 case EAP_TLS_ACK_SEND:
200 eap_round->request->code = FR_EAP_CODE_REQUEST;
201 break;
202
204 eap_round->request->code = FR_EAP_CODE_SUCCESS;
205 break;
206
207 case EAP_TLS_FAIL:
208 eap_round->request->code = FR_EAP_CODE_FAILURE;
209 break;
210
211 default:
212 /* Should never enter here */
213 fr_assert(0);
214 break;
215 }
216
217 return 0;
218}
219
220/** Send an initial EAP-TLS request to the peer.
221 *
222 * Once having received the peer's Identity, the EAP server MUST respond with an
223 * EAP-TLS/Start packet, which is an EAP-Request packet with EAP-Type = EAP-TLS,
224 * the Start (S) bit set, and no data.
225 *
226 * The EAP-TLS conversation will then begin, with the peer sending an EAP-Response
227 * packet with EAP-Type = EAP-TLS. The data field of that packet will be the TLS data.
228 *
229 * The S flag is set only within the EAP-TLS start message sent from the EAP server to the peer.
230 *
231 * - len = header + type + tls_typedata
232 * - tls_typedata = flags(Start (S) bit set, and no data)
233 *
234 * Fragment length is Framed-MTU - 4.
235 *
236 * @param[in] request The current subrequest.
237 * @param[in] eap_session to initiate.
238 * @return
239 * - 0 on success.
240 * - -1 on failure.
241 */
243{
244 eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
245
246 fr_assert(request->parent); /* must be a subrequest */
247
248 return eap_tls_compose(request, eap_session, EAP_TLS_START_SEND,
249 SET_START(eap_tls_session->base_flags), NULL, 0, 0);
250}
251
252/** Send an EAP-TLS success
253 *
254 * Composes an EAP-TLS-Success. This is a message with code EAP_TLS_ESTABLISHED.
255 * It contains no cryptographic material, and is not protected.
256 *
257 * We add the MPPE keys here. These are used by the NAS. The supplicant
258 * will derive the same keys separately.
259 *
260 * If we're using session tickets, then we call `store session` or
261 * `encode session` to save the session ticket. This is done by the
262 * application (EAP) instead TLS, because the user isn't authenticated
263 * until the inner-tunnel data says so.
264 *
265 * @note The caller MUST set the caller's own unlang result before calling
266 * eap_tls_success(). A pushed child returns to the caller's caller
267 * with that result already in place. The result is normally
268 * RLM_MODULE_OK, even if we fail to persist the session data.
269 *
270 * @param[in] request The current subrequest.
271 * @param[in] eap_session that completed successfully.
272 * @param[in] prf_label PRF label struct, or NULL to skip key generation.
273 * @return
274 * - UNLANG_ACTION_PUSHED_CHILD - cache sections are running.
275 * - UNLANG_ACTION_CALCULATE_RESULT - there was nothing more to do.
276 * - UNLANG_ACTION_FAIL - the success packet or the keys could not be created.
277 */
279{
280 eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
281 fr_tls_session_t *tls_session = eap_tls_session->tls_session;
282 uint8_t *session_id;
283 fr_pair_t *vp;
284
285 fr_assert(request->parent); /* must be a subrequest */
286
287 eap_session->finished = true;
288
289 /*
290 * Build the success packet
291 */
293 eap_tls_session->base_flags, NULL, 0, 0) < 0) return UNLANG_ACTION_FAIL;
294
295 /*
296 * EAP-FAST does it's own thing here. <sigh>
297 */
298 if (!prf_label) return fr_tls_ticket_issue(request, tls_session);
299
300 /*
301 * Automatically generate MPPE keying material.
302 */
303 if (eap_crypto_mppe_keys(request->parent, tls_session->ssl, prf_label) < 0) return UNLANG_ACTION_FAIL;
304
305 /*
306 * Add the EAP session ID to the request
307 */
309 if (eap_crypto_tls_session_id(vp, request, tls_session->ssl, prf_label,
310 &session_id, eap_session->type) < 0) {
312 return UNLANG_ACTION_FAIL;
313 }
314 fr_pair_value_memdup_buffer_shallow(vp, session_id, false);
315
316 RINDENT();
317 RDEBUG2("reply.%pP", vp);
318 REXDENT();
319
320 return fr_tls_ticket_issue(request, tls_session);
321}
322
323/** Send an EAP-TLS failure
324 *
325 * Composes an EAP-TLS-Failure. This is a message with code EAP_TLS_FAILURE.
326 * It contains no cryptographic material, and is not protected.
327 *
328 * In addition to sending the failure, will destroy any cached session data.
329 *
330 * The caller MUST set the caller's own p_result->rcode before calling this function.
331 *
332 * @param[in] request The current subrequest.
333 * @param[in] eap_session that failed.
334 * @return
335 * - UNLANG_ACTION_PUSHED_CHILD - cache sections are running.
336 * - UNLANG_ACTION_CALCULATE_RESULT - there was no cache work to do.
337 * - UNLANG_ACTION_FAIL - the frame could not be pushed.
338 */
340{
341 eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
342 fr_tls_session_t *tls_session = eap_tls_session->tls_session;
343
344 fr_assert(request->parent); /* must be a subrequest */
345
346 eap_session->finished = true;
347
348 if (eap_tls_compose(request, eap_session, EAP_TLS_FAIL,
349 eap_tls_session->base_flags, NULL, 0, 0) < 0) {
350 REDEBUG("Failed composing EAP-Failure");
351 }
352
353 /*
354 * Authentication failed. Run "fail session", cancel
355 * any queued "store session", and then run "clear
356 * session".
357 */
358 return fr_tls_session_fail_session(request, tls_session, true);
359}
360
361/** Frames the OpenSSL data that needs to be sent to the client in an EAP-Request
362 *
363 * A single TLS record may be up to 16384 octets in length, but a TLS message
364 * may span multiple TLS records, and a TLS certificate message may theoretically,
365 * be as big as 16MB.
366 *
367 * In EAP-TLS with no inner method, this is used primarily to send our certificate
368 * chain to the peer.
369 *
370 * In other methods this function is also called to package up application data
371 * for the inner tunnel method.
372 *
373 * The eap_tls_session->length_included flag determines whether we include the extra
374 * four byte length field in the request and set the L flag.
375 *
376 * If present, the tls_length field indicates the total length of the reassembled
377 * TLS record.
378 *
379 * If eap_tls_session->length_included this means we include L flag and the tls_length
380 * field in EVERY packet we send out.
381 *
382 * If !eap_tls_session->length_included this means we include L flag and tls_length
383 * field **ONLY** in First packet of a fragment series. We do not use it anywhere
384 * else.
385 *
386 * @param request the request
387 * @param eap_session that's continuing.
388 * @return
389 * - 0 on success.
390 * - -1 on failure.
391 */
393{
394 eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
395 fr_tls_session_t *tls_session = eap_tls_session->tls_session;
396 uint8_t flags = eap_tls_session->base_flags;
397 size_t frag_len;
398 bool length_included;
399
400 /*
401 * We don't need to always include the length
402 * (just in the first fragment) but it is
403 * configurable for compatibility.
404 */
405 length_included = eap_tls_session->include_length;
406
407 /*
408 * If this is the first fragment, record the complete
409 * TLS record length.
410 */
411 if (eap_tls_session->record_out_started == false) {
412 eap_tls_session->record_out_total_len = fr_dbuff_remaining(tls_session->dirty_out);
413 }
414
415 /*
416 * If the data we're sending is greater than the MTU
417 * then we need to fragment it.
418 */
419 if ((fr_dbuff_remaining(tls_session->dirty_out) +
420 (length_included ? TLS_HEADER_LENGTH_FIELD_LEN : 0)) > tls_session->mtu) {
421 if (eap_tls_session->record_out_started == false) length_included = true;
422
423 frag_len = length_included ? tls_session->mtu - TLS_HEADER_LENGTH_FIELD_LEN:
424 tls_session->mtu;
425
426 flags = SET_MORE_FRAGMENTS(flags);
427
428 /*
429 * Length MUST be included if we're record_out_started
430 * and this is the first fragment.
431 */
432 if (eap_tls_session->record_out_started == false) {
433 RDEBUG2("Complete TLS record (%zu bytes) larger than MTU (%zu bytes), will fragment",
434 eap_tls_session->record_out_total_len, frag_len); /* frag_len is correct here */
435 RDEBUG2("Sending first TLS record fragment (%zu bytes), %zu bytes remaining",
436 frag_len, fr_dbuff_remaining(tls_session->dirty_out) - frag_len);
437 } else {
438 RDEBUG2("Sending additional TLS record fragment (%zu bytes), %zu bytes remaining",
439 frag_len, fr_dbuff_remaining(tls_session->dirty_out) - frag_len);
440 }
441 eap_tls_session->record_out_started = true; /* Start a new series of fragments */
442 /*
443 * Otherwise, we're either sending a record smaller
444 * than the MTU or this is the final fragment.
445 */
446 } else {
447 frag_len = fr_dbuff_remaining(tls_session->dirty_out); /* Remaining data to drain */
448
449 if (eap_tls_session->record_out_started == false) {
450 RDEBUG2("Sending complete TLS record (%zu bytes)", frag_len);
451 } else {
452 RDEBUG2("Sending final TLS record fragment (%zu bytes)", frag_len);
453 }
454 eap_tls_session->record_out_started = false;
455 }
456
457 /*
458 * Update the flags to say we're including the
459 * TLS record length.
460 */
461 if (length_included) flags = SET_LENGTH_INCLUDED(flags);
462
463 return eap_tls_compose(request, eap_session, EAP_TLS_RECORD_SEND, flags,
464 tls_session->dirty_out, eap_tls_session->record_out_total_len, frag_len);
465}
466
467/** ACK a fragment of the TLS record from the peer
468 *
469 * EAP server sends an ACK when it determines there are More fragments to
470 * receive to make the complete TLS-record.
471 *
472 * When the EAP server receives an EAP-Response with the M bit set, it MUST
473 * respond with an EAP-Request with EAP-Type = EAP-TLS and no data. This serves
474 * as a fragment ACK.
475 *
476 * In order to prevent errors in the processing of fragments, the EAP server
477 * MUST use increment the Identifier value for each fragment ACK contained
478 * within an EAP-Request, and the peer MUST include this Identifier value in
479 * the subsequent fragment contained within an EAP-Reponse.
480 *
481 * @param[in] request The current subrequest.
482 * @param[in] eap_session that we're acking the fragment for.
483 */
484static int eap_tls_ack(request_t *request, eap_session_t *eap_session)
485{
486 eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
487
488 fr_assert(request->parent); /* must be a subrequest */
489
490 RDEBUG2("ACKing Peer's TLS record fragment");
491 return eap_tls_compose(request, eap_session, EAP_TLS_ACK_SEND,
492 eap_tls_session->base_flags, NULL, 0, 0);
493}
494
495/** Reduce session states down into an easy to use status
496 *
497 * @param[in] request The current subrequest.
498 * @param[in] eap_session that we're acking the fragment for.
499 * @return
500 * - EAP_TLS_ESTABLISHED - Handshake completed.
501 * - EAP_TLS_FAIL - Fatal alert from the client.
502 * - EAP_TLS_RECORD_SEND - Need more data, or previous fragment was acked.
503 */
505{
506 eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
507 fr_tls_session_t *tls_session = eap_tls_session->tls_session;
508
509 if (tls_session == NULL){
510 REDEBUG("Unexpected ACK received: No ongoing SSL tls_session");
511 return EAP_TLS_INVALID;
512 }
513 if (!tls_session->info.initialized) {
514 RDEBUG2("No SSL info available. Waiting for more SSL data");
515 return EAP_TLS_RECORD_SEND;
516 }
517
518 if ((tls_session->info.content_type == SSL3_RT_HANDSHAKE) &&
519 (tls_session->info.origin == TLS_INFO_ORIGIN_RECORD_RECEIVED)) {
520 REDEBUG("Unexpected ACK received: We sent no previous messages");
521 return EAP_TLS_INVALID;
522 }
523
524 switch (tls_session->info.content_type) {
525 case SSL3_RT_ALERT:
526 RDEBUG2("Peer ACKed our alert");
527 return EAP_TLS_FAIL;
528
529 case SSL3_RT_HANDSHAKE:
530 if (fr_tls_session_is_init_finished(tls_session) && (fr_dbuff_remaining(tls_session->dirty_out) == 0)) {
531 RDEBUG2("Peer ACKed our handshake fragment. handshake is finished");
532
533 /*
534 * From now on all the content is
535 * application data set it here as nobody else
536 * sets it.
537 */
538 tls_session->info.content_type = SSL3_RT_APPLICATION_DATA;
539 return EAP_TLS_ESTABLISHED;
540 } /* else more data to send */
541
542 RDEBUG2("Peer ACKed our handshake fragment");
543 /* Fragmentation handler, send next fragment */
544 return EAP_TLS_RECORD_SEND;
545
546 case SSL3_RT_APPLICATION_DATA:
547 RDEBUG2("Peer ACKed our application data fragment");
548 return EAP_TLS_RECORD_SEND;
549
550 /*
551 * For the rest of the conditions, switch over
552 * to the default section below.
553 */
554 default:
555 /*
556 * If the last message was from us, then the session is established or we're still
557 * sending the session ticket.
558 */
559 if (tls_session->info.origin == TLS_INFO_ORIGIN_RECORD_SENT) {
560 if (fr_dbuff_remaining(tls_session->dirty_out) == 0) return EAP_TLS_ESTABLISHED;
561 return EAP_TLS_RECORD_SEND;
562 }
563 REDEBUG("Invalid ACK received: %d", tls_session->info.content_type);
564 return EAP_TLS_INVALID;
565 }
566}
567
568/** Check that this EAP-TLS packet is correct and the progression of EAP-TLS packets is sane
569 *
570 * @note In the received packet, No data will be present in case of ACK or NAK
571 * in this case the packet->data pointer will be NULL.
572 *
573 * @param[in] request the current subrequest.
574 * @param[in] eap_session the current EAP session state.
575 * @return
576 * - EAP_TLS_INVALID if the TLS record or progression is invalid.
577 * - EAP_TLS_FAIL handshake failed.
578 * - EAP_TLS_RECORD_RECV_FIRST this is the start of a new sequence of record fragments.
579 * - EAP_TLS_RECORD_RECV_MORE this is a continuation of a sequence of fragments.
580 * - EAP_TLS_RECORD_RECV_COMPLETE we received a completed record.
581 * - EAP_TLS_RECORD_SEND send more data to peer.
582 * - EAP_TLS_ESTABLISHED handshake is complete, TLS session has been established.
583 */
585{
586 eap_round_t *this_round = eap_session->this_round;
587 eap_round_t *prev_round = eap_session->prev_round;
588 eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
589
590 eap_tls_data_t *eap_tls_data;
591 size_t frag_len, header_len;
592
593 fr_assert(request->parent); /* must be a subrequest */
594
595 /*
596 * All EAP-TLS packets must contain type and flags fields.
597 */
598 if (this_round->response->length < (EAP_HEADER_LEN + 2)) {
599 REDEBUG("Invalid EAP-TLS packet: Expected at least %zu bytes got %zu bytes",
600 (size_t)EAP_HEADER_LEN + 2, this_round->response->length);
601 return EAP_TLS_INVALID;
602 }
603
604 /*
605 * We don't check ANY of the input parameters. It's all
606 * code which works together, so if something is wrong,
607 * we SHOULD core dump.
608 *
609 * e.g. if this_round is NULL, or if this_round->response is
610 * NULL, or if it's NOT an EAP-Response, or if the packet
611 * is too short. See eap_validate()., in ../../eap.c
612 */
613 eap_tls_data = (eap_tls_data_t *)this_round->response->type.data;
614 if (!eap_tls_data) {
615 REDEBUG("Invalid EAP-TLS packet; no data");
616 return EAP_TLS_INVALID;
617 }
618
619 /*
620 * First output the flags (for debugging)
621 */
622 RDEBUG3("Peer sent flags %c%c%c%c%c%c%c%c",
623 TLS_START(eap_tls_data->flags) ? 'S' : '-',
624 TLS_MORE_FRAGMENTS(eap_tls_data->flags) ? 'M' : '-',
625 TLS_LENGTH_INCLUDED(eap_tls_data->flags) ? 'L' : '-',
626 TLS_RESERVED0(eap_tls_data->flags) ? 'R' : '-',
627 TLS_RESERVED1(eap_tls_data->flags) ? 'R' : '-',
628 TLS_RESERVED2(eap_tls_data->flags) ? 'R' : '-',
629 TLS_RESERVED3(eap_tls_data->flags) ? 'R' : '-',
630 TLS_RESERVED4(eap_tls_data->flags) ? 'R' : '-');
631
632 /*
633 * This length includes the type and flags field and
634 * the message length field if the flags indicate it's present.
635 */
636 header_len = EAP_HEADER_LEN + (TLS_LENGTH_INCLUDED(eap_tls_data->flags) ? 6 : 2);
637 if (this_round->response->length < header_len) {
638 REDEBUG("Invalid EAP-TLS packet: Expected at least %zu bytes got %zu bytes",
639 header_len, this_round->response->length);
640 return EAP_TLS_INVALID;
641 }
642
643 /*
644 * check for ACK
645 *
646 * If there's no TLS data, or there's 1 byte of TLS data,
647 * with the flags set to zero, then it's an ACK.
648 *
649 * Find if this is a reply to the previous request sent
650 */
651 if ((this_round->response->length == EAP_HEADER_LEN + 2) &&
652 ((eap_tls_data->flags & 0xc0) == 0x00)) {
653 if (!prev_round || (prev_round->request->id != this_round->response->id)) {
654 REDEBUG("Received Invalid TLS ACK");
655 return EAP_TLS_INVALID;
656 }
657 return eap_tls_session_status(request, eap_session);
658 }
659
660 /*
661 * We send TLS_START, but do not receive it.
662 */
663 if (TLS_START(eap_tls_data->flags)) {
664 REDEBUG("Peer sent EAP-TLS Start message (only the server is allowed to do this)");
665 return EAP_TLS_INVALID;
666 }
667
668 /*
669 * Calculate this fragment's length
670 */
671 frag_len = this_round->response->length - header_len;
672
673 /*
674 * This fragment has no data, but the header says that there is more data!
675 */
676 if (!frag_len && TLS_MORE_FRAGMENTS(eap_tls_data->flags)) {
677 REDEBUG("Peer sent EAP-TLS with zero-length fragment and 'more' bit set - if there is no data, there should not be more!");
678 return EAP_TLS_INVALID;
679 }
680
681 /*
682 * The L bit (length included) is set to indicate the
683 * presence of the four octet TLS Message Length field,
684 * and MUST be set for the first fragment of a fragmented
685 * TLS message or set of messages.
686 *
687 * The M bit (more fragments) is set on all but the last
688 * fragment.
689 *
690 * The S bit (EAP-TLS start) is set in an EAP-TLS Start
691 * message. This differentiates the EAP-TLS Start message
692 * from a fragment acknowledgement.
693 */
694 if (TLS_LENGTH_INCLUDED(eap_tls_data->flags)) {
695 size_t total_len;
696
697 if (eap_tls_data->data[0] || eap_tls_data->data[1]) {
698 REDEBUG("TLS record length is > 65536");
699 return EAP_TLS_INVALID;
700 }
701
702 total_len = eap_tls_data->data[2] * 256 | eap_tls_data->data[3];
703 if (frag_len > total_len) {
704 REDEBUG("TLS fragment length (%zu bytes) greater than TLS record length (%zu bytes)",
705 frag_len, total_len);
706 return EAP_TLS_INVALID;
707 }
708
709 if (total_len > SSL3_RT_MAX_PLAIN_LENGTH) {
710 REDEBUG("Reassembled TLS record will be %zu bytes, "
711 "greater than our maximum record size (" STRINGIFY(SSL3_RT_MAX_PLAIN_LENGTH) " bytes)",
712 total_len);
713 return EAP_TLS_INVALID;
714 }
715
716 /*
717 * wpa_supplicant's implementation of PEAPv0, and likely other
718 * implementations of PEAPv0 will always include a Length flag
719 * for every record fragment if performing mutual TLS auth.
720 *
721 * If the eap_session says this is not the first fragment, then
722 * don't count this as a new record, and continue as if we
723 * hadn't seen the length flag.
724 */
725 if (eap_tls_session->record_in_started) goto ignore_length;
726
727 /*
728 * This is the first fragment of a fragmented TLS record transfer.
729 */
730 RDEBUG2("Peer indicated complete TLS record size will be %zu bytes", total_len);
731 if (TLS_MORE_FRAGMENTS(eap_tls_data->flags)) {
732 /*
733 * The peer is free to send fragments of wildly varying
734 * lengths, but the vast majority won't.
735 *
736 * In this calculation we take into account the fact that the future
737 * fragments are likely to be 4 bytes larger than the initial one
738 * as they won't contain the length field.
739 */
740 if (frag_len + 4) { /* check for wrap, else clang scan gets excited */
741 RDEBUG2("Expecting %i TLS record fragments",
742 (int)((((total_len - frag_len) + ((frag_len + 4) - 1)) / (frag_len + 4)) + 1));
743 }
744
745 /*
746 * First fragment. record_in_started bool was false,
747 * and we received a length included + more fragments packet.
748 */
749 RDEBUG2("Got first TLS record fragment (%zu bytes). Peer indicated more fragments "
750 "to follow", frag_len);
751 eap_tls_session->record_in_total_len = total_len;
752 eap_tls_session->record_in_recvd_len = frag_len;
753 eap_tls_session->record_in_started = true;
754
756 }
757
758 /*
759 * Else this is the complete TLS record.
760 */
761 if (total_len != frag_len) {
762 REDEBUG("Peer indicated no more fragments, but TLS record length (%zu bytes) "
763 "does not match EAP-TLS data length (%zu bytes)", total_len, frag_len);
764 return EAP_TLS_INVALID;
765 }
766
767 /*
768 * RFC5216 doesn't specify explicitly whether a non-fragmented
769 * packet should include the length or not.
770 *
771 * We support both options for maximum compatibility.
772 */
773 RDEBUG2("Got complete TLS record, with length field (%zu bytes)", frag_len);
775 }
776
777ignore_length:
778 if (TLS_MORE_FRAGMENTS(eap_tls_data->flags)) {
779 /*
780 * If this is not an ongoing transfer, and we have the M flag
781 * then this record transfer is invalid.
782 */
783 if (!eap_tls_session->record_in_started) {
784 REDEBUG("TLS More (M) flag set, but no fragmented record transfer was in progress");
785 return EAP_TLS_INVALID;
786 }
787
788 /*
789 * If this is an ongoing transfer, and we have the M flag,
790 * then this is just an additional fragment.
791 */
792 RDEBUG2("Got additional TLS record fragment (%zu bytes). Peer indicated more fragments to follow",
793 frag_len);
794 eap_tls_session->record_in_recvd_len += frag_len;
795 if (eap_tls_session->record_in_recvd_len > eap_tls_session->record_in_total_len) {
796 REDEBUG("Total received TLS record fragments (%zu bytes), exceeds "
797 "indicated TLS record length (%zu bytes)",
798 eap_tls_session->record_in_recvd_len, eap_tls_session->record_in_total_len);
799 return EAP_TLS_INVALID;
800 }
802 }
803
804 /*
805 * No L flag and no M flag. This is either the final fragment,
806 * or a new transfer that was not started with a L flag, which
807 * RFC5216 hints, may be acceptable.
808 *
809 * If it's an in-progress record transfer, check we now have
810 * the complete record.
811 */
812 if (eap_tls_session->record_in_started) {
813 eap_tls_session->record_in_started = false;
814
815 RDEBUG2("Got final TLS record fragment (%zu bytes)", frag_len);
816 eap_tls_session->record_in_recvd_len += frag_len;
817 if (eap_tls_session->record_in_recvd_len != eap_tls_session->record_in_total_len) {
818 REDEBUG("Total received TLS record fragments (%zu bytes), does not equal indicated "
819 "TLS record length (%zu bytes)",
820 eap_tls_session->record_in_recvd_len, eap_tls_session->record_in_total_len);
821 return EAP_TLS_INVALID;
822 }
824 }
825
826 /*
827 * None of the flags are set, it wasn't an in progress transfer,
828 * but it's still a valid EAP-TLS packet.
829 */
830 RDEBUG2("Got complete TLS record (%zu bytes)", frag_len);
831
833}
834
835/** Process the result from the last TLS handshake round
836 *
837 * @return
838 * - eap_tls_session->state == EAP_TLS_FAIL if the message is invalid.
839 * - eap_tls_session->state == EAP_TLS_HANDLED if we need to send an
840 * additional request to the peer.
841 * - eap_tls_session->state == EAP_TLS_ESTABLISHED if the handshake
842 * completed successfully, and there's no more data to send.
843 */
845{
846 eap_session_t *eap_session = talloc_get_type_abort(uctx, eap_session_t);
847 eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
848 fr_tls_session_t *tls_session = talloc_get_type_abort(eap_tls_session->tls_session, fr_tls_session_t);
850
851 switch (tls_session->result) {
852 case FR_TLS_RESULT_IN_PROGRESS:
853 default:
854 fr_assert(0); /* Shouldn't have been called */
855 goto fail;
856
857 case FR_TLS_RESULT_ERROR:
858 REDEBUG("TLS receive handshake failed during operation");
859 goto fail;
860
861 case FR_TLS_RESULT_SUCCESS:
862 break;
863 }
864
865 /*
866 * RFC 9190 Section 2.5
867 *
868 * We need to signal the other end that TLS negotiation
869 * is done. We can't send a zero-length application data
870 * message, so we send application data which is one byte
871 * of zero. This also pushes out any stateless session
872 * tickets to the peer.
873 *
874 * Note this is only done for when there is no application
875 * data to be sent. So this is done always for EAP-TLS but
876 * notibly not for PEAP even on resumption.
877 *
878 * We only want to send this application data IF:
879 *
880 * * EAP-TLS / TTLS / PEAP - session was resumed
881 * * EAP-TLS
882 * * SSL init is finished (presumed to be checked elsewhere)
883 * * we saw the client cert
884 * * OR we're using unauthenticated EAP-TLS where
885 * the administrator has decided to not ask for
886 * the client cert
887 */
888 if ((tls_session->info.version == TLS1_3_VERSION) &&
889 (tls_session->peer_cert_ok || eap_tls_session->authentication_success || SSL_session_reused(tls_session->ssl))) {
890 if ((eap_session->type == FR_EAP_METHOD_TLS) || SSL_session_reused(tls_session->ssl)) {
891 eap_tls_session->authentication_success = true;
892
893 /*
894 * Ensure only a single instance of the application data is added.
895 * Some handshakes result in multiple passes through this path.
896 */
897 if (!tls_session->sent_commitment) {
898 RDEBUG2("(TLS) EAP Sending final Commitment Message.");
899 (void) fr_dbuff_in_bytes(&tls_session->clean_in, (uint8_t) 0x00);
900 tls_session->sent_commitment = true;
901 }
902
903 /*
904 * Write out the application data if the session is ready for it.
905 */
906 if (SSL_is_init_finished(tls_session->ssl)) fr_tls_session_send(request, tls_session);
907 } else {
908
909 /*
910 * Returns UNLANG_ACTION_PUSHED_CHILD unless something has failed
911 */
912 ret = fr_tls_session_async_handshake_push(request, tls_session);
913 if (ret != UNLANG_ACTION_FAIL) return ret;
914
915 REDEBUG("TLS receive handshake failed during operation");
916 goto fail;
917 }
918 }
919
920 /*
921 * FIXME: return success/fail.
922 *
923 * TLS proper can decide what to do, then.
924 */
925 if (fr_dbuff_remaining(tls_session->dirty_out) > 0) {
926 /*
927 * If the handshake is finished and we have application data
928 * then move to phase2.
929 * This happens when a client sends application data in the
930 * same packet as the handshake finished record, but OpenSSL
931 * has decided to send a NewSessionTicket.
932 * The client isn't expecting a ticket at this point.
933 */
934 if (tls_session->seen_application_data && fr_dbuff_used(&tls_session->clean_out) > 0) goto phase2;
935
936 if (eap_tls_request(request, eap_session) < 0) {
937 REDEBUG("TLS failed composing a response");
938 goto fail;
939 }
940 eap_tls_session->state = EAP_TLS_HANDLED;
942 }
943
944 /*
945 * If there is no data to send, and
946 * if the SSL handshake is finished, then return
947 * EAP_TLS_ESTABLISHED.
948 *
949 * For EAP-TLS this translates to an EAP-Success, for others
950 * this begins phase2.
951 */
952 if (eap_tls_session->phase2 || fr_tls_session_is_init_finished(tls_session)) {
953 phase2:
954 eap_tls_session->phase2 = true;
955
956 /*
957 * Init is finished. The rest is
958 * application data.
959 */
960 tls_session->info.content_type = SSL3_RT_APPLICATION_DATA;
961 eap_tls_session->state = EAP_TLS_ESTABLISHED;
963 }
964
965 /*
966 * Who knows what happened...
967 */
968 REDEBUG("TLS failed during operation");
969fail:
970 eap_tls_session->state = EAP_TLS_FAIL;
971
972 /*
973 * Record that the handshake failed, and let the caller deal
974 * with it.
975 *
976 * Every caller reaches eap_tls_fail(), which runs
977 * "fail session" and discards the session. Doing either of
978 * those here as well would run the policy twice for one
979 * failure.
980 */
982}
983
984/** Push functions to continue the handshake asynchronously
985 *
986 * @param[in] request the current subrequest.
987 * @param[in] eap_session to continue.
988 * @return
989 * - UNLANG_ACTION_PUSHED_CHILD
990 */
991static inline CC_HINT(always_inline) unlang_action_t eap_tls_handshake_push(request_t *request, eap_session_t *eap_session)
992{
993 eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
994 fr_tls_session_t *tls_session = talloc_get_type_abort(eap_tls_session->tls_session, fr_tls_session_t);
996
997 /*
998 * Will run after the handshake round completes
999 */
1001 NULL,
1003 NULL,
1005 eap_session) < 0) return UNLANG_ACTION_FAIL;
1006
1007 if (!fr_cond_assert((ua = fr_tls_session_async_handshake_push(request, tls_session)) == UNLANG_ACTION_PUSHED_CHILD)) {
1008 unlang_interpet_frame_discard(request); /* Pop the resume function */
1009 return UNLANG_ACTION_FAIL;
1010 }
1011
1012 return ua;
1013}
1014
1015/** Process an EAP TLS request
1016 *
1017 * Here we implement a basic state machine. The state machine is implicit and
1018 * is driven by the state of the TLS session and the flags sent.
1019 * INCOMING DATA:
1020 * 1. EAP-TLS should get the complete TLS data from the peer.
1021 * 2. Store that data in a data structure with any other required info
1022 * 3. Hand this data structure to the TLS module.
1023 * 4. TLS module will perform its operations on the data and hands back to EAP-TLS
1024 * OUTGOING DATA:
1025 * 1. EAP-TLS if necessary will fragment it and send it to the destination.
1026 *
1027 * During EAP-TLS initialization, TLS Context object will be initialised and stored.
1028 * For every new authentication request, TLS will open a new session object and that
1029 * session object SHOULD be maintained even after the session is completed, for session
1030 * resumption.
1031 *
1032 * Note that we never return FAIL to the interpreter. Instead, we
1033 * send the EAP failure back to the supplicant.
1034 *
1035 * @param request the request
1036 * @param eap_session to continue.
1037 * @return
1038 * - UNLANG_ACTION_CALCULATE_RESULT
1039 */
1041{
1042 eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
1043 fr_tls_session_t *tls_session = eap_tls_session->tls_session;
1044
1045 eap_round_t *this_round = eap_session->this_round;
1046
1047 eap_tls_data_t *eap_tls_data;
1048 uint8_t *data;
1049 size_t data_len;
1050
1051 fr_assert(request->parent); /* must be a subrequest */
1052
1053 RDEBUG2("Continuing EAP-TLS");
1054
1055 /*
1056 * Call eap_tls_verify to sanity check the incoming EAP data.
1057 */
1058 eap_tls_session->state = eap_tls_verify(request, eap_session);
1059 switch (eap_tls_session->state) {
1060 case EAP_TLS_INVALID:
1061 case EAP_TLS_FAIL:
1062 REDEBUG("[eap-tls verify] = %s", fr_table_str_by_value(eap_tls_status_table, eap_tls_session->state, "<INVALID>"));
1063 break;
1064
1065 default:
1066 RDEBUG2("[eap-tls verify] = %s", fr_table_str_by_value(eap_tls_status_table, eap_tls_session->state, "<INVALID>"));
1067 break;
1068 }
1069
1070 /*
1071 * Status in this here means 'state'. Our state is determined passively
1072 * for EAP-TLS, based on what state OpenSSL reported the TLS session
1073 * to be in, and what flags were last received from the peer.
1074 */
1075 switch (eap_tls_session->state) {
1076 /*
1077 * We've received a complete TLS record, this is the same as receiving a
1078 * fragment, except we also process the complete record.
1079 */
1081 /*
1082 * We've received a fragment of a TLS record
1083 *
1084 * Determine where the TLS record starts.
1085 *
1086 * If the length included flag is set, we need to skip over the 4 byte
1087 * message length field.
1088 *
1089 * Next - Copy the fragment data into OpenSSL's dirty in buffer so that it
1090 * can process it in a later call.
1091 */
1094 eap_tls_data = (eap_tls_data_t *)this_round->response->type.data;
1095 if (TLS_LENGTH_INCLUDED(eap_tls_data->flags)) {
1096 data = (this_round->response->type.data + 5); /* flags + TLS-Length */
1097 data_len = this_round->response->type.length - 5; /* flags + TLS-Length */
1098 } else {
1099 data = this_round->response->type.data + 1; /* flags */
1100 data_len = this_round->response->type.length - 1; /* flags */
1101 }
1102
1103 /*
1104 * Update the dirty_in buffer (data for reading by OpenSSL)
1105 *
1106 * OpenSSL reads this, and writes clean data out.
1107 * The dirty_in buffer may contain partial TLS
1108 * records on exit.
1109 */
1110 if (fr_dbuff_in_memcpy_partial(tls_session->dirty_in, data, data_len) != data_len) {
1111 REDEBUG("Exceeded maximum record size");
1112 eap_tls_session->state = EAP_TLS_FAIL;
1113 goto done;
1114 }
1115
1116 /*
1117 * ACK fragments until we get a complete TLS record.
1118 */
1119 if (eap_tls_session->state != EAP_TLS_RECORD_RECV_COMPLETE) {
1120 if (eap_tls_ack(request, eap_session) < 0) {
1121 eap_tls_session->state = EAP_TLS_FAIL;
1122 } else {
1123 eap_tls_session->state = EAP_TLS_HANDLED;
1124 }
1125 goto done;
1126 }
1127
1128 /*
1129 * We have a complete record. If the handshake is finished
1130 * process it as application data, otherwise continue
1131 * the handshake.
1132 */
1133 if (eap_tls_session->phase2 || fr_tls_session_is_init_finished(tls_session)) {
1134 int ret;
1135
1136 eap_tls_session->phase2 = true;
1137
1138 ret = fr_tls_session_recv(request, tls_session);
1139 switch (ret) {
1140 case 0:
1141 eap_tls_session->state = EAP_TLS_RECORD_RECV_COMPLETE;
1142 break;
1143
1144 case 1:
1145 eap_tls_session->state = EAP_TLS_RECORD_RECV_MORE;
1146 break;
1147
1148 default:
1149 eap_tls_session->state = EAP_TLS_FAIL;
1150 break;
1151 }
1152 } else {
1153 /*
1154 * Asynchronously process more handshake data
1155 */
1156 return eap_tls_handshake_push(request, eap_session);
1157 }
1158 break;
1159 /*
1160 * We have fragments or records to send to the peer
1161 */
1163 /*
1164 * Return a "yes we're done" if there's no more data to send,
1165 * and we've just managed to finish the SSL session initialization.
1166 */
1167 if (!eap_tls_session->phase2 && (fr_dbuff_remaining(tls_session->dirty_out) == 0) &&
1168 fr_tls_session_is_init_finished(tls_session)) {
1169 eap_tls_session->phase2 = true;
1170 eap_tls_session->state = EAP_TLS_ESTABLISHED;
1171 goto done;
1172 }
1173
1174 if (eap_tls_request(request, eap_session) < 0) {
1175 eap_tls_session->state = EAP_TLS_FAIL;
1176 } else {
1177 eap_tls_session->state = EAP_TLS_HANDLED;
1178 }
1179 goto done;
1180
1181 /*
1182 * Bad things happened and we're unable to continue.
1183 */
1184 case EAP_TLS_INVALID:
1185 case EAP_TLS_FAIL:
1186 /*
1187 * Established means that we're done the initial handshake.
1188 *
1189 * For TTLS and PEAP that means begin phase2
1190 */
1192 default:
1193 goto done;
1194 }
1195
1196 done:
1197
1199}
1200
1201/** Create a new fr_tls_session_t associated with an #eap_session_t
1202 *
1203 * Creates a new server fr_tls_session_t and associates it with an #eap_session_t
1204 * adding EAP specific opaque data to the SSL session created during fr_tls_session_t
1205 * initialisation.
1206 *
1207 * @param[in] request The current subrequest.
1208 * @param[in] eap_session to use as a context for the eap_tls_session_t
1209 * @param[in] ssl_ctx to use to configure the fr_tls_session_t.
1210 * @param[in] client_cert Whether we require the peer to prevent a certificate.
1211 * @return
1212 * - A new eap_tls_session on success.
1213 * - NULL on error.
1214 */
1216 SSL_CTX *ssl_ctx, bool client_cert)
1217{
1218 eap_tls_session_t *eap_tls_session;
1219 fr_tls_session_t *tls_session;
1220 fr_tls_conf_t *conf = fr_tls_ctx_conf(ssl_ctx);
1221 fr_pair_t *vp;
1222 fr_pair_t *tls_max, *tls_min;
1223
1224 fr_assert(request->parent); /* must be a subrequest */
1225
1226 /*
1227 * This EAP session is associated with a TLS session
1228 */
1229 eap_session->tls = true;
1230 MEM(eap_tls_session = talloc_zero(eap_session, eap_tls_session_t));
1231
1232 /*
1233 * Initial state.
1234 */
1235 eap_tls_session->state = EAP_TLS_START_SEND;
1236
1237 /*
1238 * As per the RFC...
1239 *
1240 * Broken protocols like PEAPv0 need this set to false.
1241 */
1242 eap_tls_session->include_length = true;
1243
1244 /*
1245 * We use default fragment size, unless the Framed-MTU
1246 * tells us it's too big. Note that we do NOT account
1247 * for the EAP-TLS headers if conf->fragment_size is
1248 * large, because that config item looks to be confusing.
1249 *
1250 * i.e. it should REALLY be called MTU, and the code here
1251 * should figure out what that means for TLS fragment size.
1252 * asking the administrator to know the internal details
1253 * of EAP-TLS in order to calculate fragment sizes is
1254 * just too much.
1255 */
1256 vp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_framed_mtu);
1257
1258 /*
1259 * TLS 1.3 introduces the concept of early data (also known as zero
1260 * round trip data or 0-RTT data). Early data allows a client to send
1261 * data to a server in the first round trip of a connection, without
1262 * waiting for the TLS handshake to complete if the client has spoken
1263 * to the same server recently. This doesn't work for EAP, so we
1264 * disable early data.
1265 */
1266 SSL_CTX_set_max_early_data(ssl_ctx, 0);
1267
1268 /*
1269 * Every new session is started only from EAP-TLS-START.
1270 * Before Sending our initial EAP-TLS start open a new
1271 * SSL session.
1272 * Create all the required data structures & store them
1273 * in the SSL session's opaque data so that we can use
1274 * these data structures when we get the response.
1275 */
1276 eap_tls_session->tls_session = tls_session = fr_tls_session_alloc_server(eap_tls_session, ssl_ctx,
1277 request, client_cert);
1278 if (unlikely(!tls_session)) return NULL;
1279
1280 /*
1281 * EAP-TTLS cannot reliably use stateless session tickets with TLS 1.3.
1282 *
1283 * See src/lib/tls/session.c for explanations.
1284 */
1285 switch (eap_session->type) {
1286 case FR_EAP_METHOD_TTLS:
1287 tls_session->disallow_stateless_tickets = true;
1288 break;
1289
1290 default:
1291 break;
1292 }
1293
1294 /*
1295 * Set our MTU, and enforce dynamic MTU
1296 *
1297 * Account for the EAP header (4), and the EAP-TLS header
1298 * (6), as per Section 4.2 of RFC 2716. What's left is
1299 * the maximum amount of data we read from a TLS buffer.
1300 */
1301 tls_session->mtu = conf->fragment_size - 10;
1302 if (vp && (vp->vp_uint32 > 100) && (vp->vp_uint32 < tls_session->mtu)) {
1303 RDEBUG2("Setting fragment_len from %pP", vp);
1304 tls_session->mtu = vp->vp_uint32;
1305 }
1306
1307 /*
1308 * Track EAP-TLS inside of a tunneled method. The outer TLS session encrypts each inner packet,
1309 * which adds a record header, plus the IV, MAC or tag, and padding. The inner MTU therefore
1310 * needs to be smaller than the outer one, so that the inner TLS fragments fit within the outer
1311 * TLS fragments.
1312 */
1313 if (eap_session_in_tunnel(eap_session->request) && (tls_session->mtu > (EAP_TLS_NESTED_OVERHEAD + 100))) {
1314 tls_session->mtu -= EAP_TLS_NESTED_OVERHEAD;
1315 RDEBUG2("Nested inside another EAP method, lowering fragment_len to %zu", tls_session->mtu);
1316 }
1317
1318 /*
1319 * Add the EAP-Identity value to the TLS session so
1320 * it's available in all the TLS callbacks.
1321 */
1322 {
1323 fr_pair_t *identity;
1324
1325 MEM(identity = fr_pair_afrom_da(tls_session, attr_eap_identity));
1326 fr_pair_value_bstrdup_buffer(identity, eap_session->identity, true);
1327 fr_tls_session_extra_pair_add_shallow(tls_session, identity);
1328 }
1329
1330 /*
1331 * Add the EAP-Type we're running to the subrequest.
1332 */
1333 {
1334 fr_pair_t *type_vp;
1335
1336 MEM(type_vp = fr_pair_afrom_da(tls_session, attr_eap_type));
1337 type_vp->vp_uint32 = eap_session->type;
1338 fr_tls_session_extra_pair_add_shallow(tls_session, type_vp);
1339 }
1340
1341 /*
1342 * Associate various bits of opaque data with the session.
1343 */
1344 SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_EAP_SESSION, (void *)eap_session);
1345 SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_TLS_SESSION, (void *)tls_session);
1346 SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_CONF, (void *)conf);
1347 SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_IDENTITY, (void *)&(eap_session->identity));
1348
1349 tls_max = fr_pair_find_by_da(&request->control_pairs, NULL, attr_tls_max_version);
1350 tls_min = fr_pair_find_by_da(&request->control_pairs, NULL, attr_tls_min_version);
1351 if (tls_max && tls_min && (tls_min->vp_float32 > tls_max->vp_float32)) {
1352 RERROR("Can't set TLS min version greater than max version");
1353 goto skip_tls_version;
1354 }
1355
1356#define SET_TLS_VERSION(_type) \
1357 if (tls_ ## _type) { \
1358 int tls_version = 0; \
1359 if (tls_ ## _type->vp_float32 >= (float) 1.3) { \
1360 tls_version = TLS1_3_VERSION; \
1361 } else if (tls_ ## _type->vp_float32 >= (float) 1.2) { \
1362 tls_version = TLS1_2_VERSION; \
1363 } else if (tls_ ## _type->vp_float32 >= (float) 1.1) { \
1364 tls_version = TLS1_1_VERSION; \
1365 } \
1366 if (tls_version) { \
1367 if (SSL_set_ ## _type ## _proto_version(tls_session->ssl, tls_version) != 1) {\
1368 RERROR("Failed to set %pP", tls_ ## _type); \
1369 } else { \
1370 RDEBUG2("Setting TLS " #_type " version to %0.1f", (double) tls_ ## _type->vp_float32); \
1371 } \
1372 } else { \
1373 RWARN("Invalid value %pP", tls_ ## _type); \
1374 } \
1375 }
1376
1379skip_tls_version:
1380
1381 return eap_tls_session;
1382}
1383
1384/** Apply the limits that EAP puts on a parsed `tls { ... }` section
1385 *
1386 * The submodule's own rules parse the section, through the
1387 * `FR_CONF_SUBSECTION_ALLOC` row that names `fr_tls_server_config`.
1388 *
1389 * @param[in] cs the submodule's section.
1390 * @param[in,out] tls_conf parsed from the `tls { ... }` subsection.
1391 * @param[in] delayed_tickets Does this EAP type need delayed session tickets.
1392 */
1393void eap_tls_conf_check(CONF_SECTION *cs, fr_tls_conf_t *tls_conf, bool delayed_tickets)
1394{
1395 /*
1396 * There isn't any point to having EAP sessions cache
1397 * lifetimes which are very low. Arguably, the minimum
1398 * lifetime should be a few hours. We only limit it here
1399 * to 15min, because anything lower is pretty much
1400 * ridiculous.
1401 *
1402 * If the administrator also sets it too low, then we
1403 * raise it.
1404 */
1405 if (!tls_conf->cache.min_lifetime_is_set ||
1406 fr_time_delta_lt(tls_conf->cache.min_lifetime, fr_time_delta_from_sec(15 * 60))) {
1407 tls_conf->cache.min_lifetime = fr_time_delta_from_sec(15 * 60);
1408 cf_log_warn_by_child(cs, "tls", "Raising EAP session.min_lifetime to %pV",
1409 fr_box_time_delta(tls_conf->cache.min_lifetime));
1410 }
1411
1412 /*
1413 * Most EAP methods send the ticket after the authentication has succeeded, not in the TLS handshake.
1414 */
1415 tls_conf->delayed_tickets = delayed_tickets;
1416}
1417
1418/** Check that the TLS configuration does not need stateless session tickets
1419 *
1420 * EAP-TTLS does not use stateless session tickets with TLS 1.3. TTLS sessions set
1421 * `disallow_stateless_tickets`, and the ticket code creates no stateless ticket.
1422 *
1423 * - `session.mode = "stateless"` needs stateless tickets, so with TLS 1.3 allowed the method
1424 * cannot work as configured. That is an error.
1425 * - `session.mode = "auto"` allows stateless tickets, but does not need them. That is a warning.
1426 *
1427 * @param[in] cs the submodule's section.
1428 * @param[in] tls_conf parsed from the `tls { ... }` subsection.
1429 * - 0 on success.
1430 * - -1 if the configuration requires stateless session tickets.
1431 */
1432int eap_tls_check_stateless(CONF_SECTION *cs, fr_tls_conf_t const *tls_conf)
1433{
1434 /*
1435 * No TLS 1.3 means no stateless tickets, which TLS 1.2 and earlier do not use.
1436 */
1437 if ((tls_conf->tls_max_version > 0) && (tls_conf->tls_max_version < (float)1.3)) return 0;
1438
1439 if (!(tls_conf->cache.mode & FR_TLS_TICKET_STATELESS)) return 0;
1440
1441 if (tls_conf->cache.mode == FR_TLS_TICKET_AUTO) {
1442 cf_log_warn_by_child(cs, "tls", "Stateless session tickets do not work with this EAP method, "
1443 "and are not used with TLS 1.3");
1444 return 0;
1445 }
1446
1447 cf_log_err_by_child(cs, "tls", "session.mode = \"stateless\" does not work with this EAP method, "
1448 "which does not use stateless session tickets with TLS 1.3.");
1449
1450 /*
1451 * `auto` is rewritten to `stateless` when there is no stateful cache. The administrator
1452 * still asked for `auto`.
1453 */
1454 if (tls_conf->cache.mode_is_auto) {
1455 cf_log_warn_by_child(cs, "tls", "Add a 'store session { ... }' section to save stateful tickets, or");
1456 cf_log_warn_by_child(cs, "tls", "use session.mode = \"disabled\",");
1457 } else {
1458 cf_log_warn_by_child(cs, "tls", "Use session.mode = \"auto\" or \"disabled\",");
1459 }
1460 cf_log_warn_by_child(cs, "tls", "or set tls_max_version = 1.2");
1461
1462 return -1;
1463}
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:40
@ 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:38
static uint8_t request[4]
#define USES_APPLE_DEPRECATED_API
Definition build.h:590
#define RCSID(id)
Definition build.h:603
#define L(_str)
Helper for initialising arrays of string literals.
Definition build.h:245
#define STRINGIFY(x)
Definition build.h:233
#define unlikely(_x)
Definition build.h:486
#define NUM_ELEMENTS(_t)
Definition build.h:437
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:106
#define cf_log_err_by_child(_parent, _child, _fmt,...)
Log an error message against a specified child.
Definition cf_util.h:367
#define cf_log_warn_by_child(_parent, _child, _fmt,...)
Log a warning message against a specified child.
Definition cf_util.h:386
eap_type_data_t type
Definition compose.h:38
size_t length
Definition compose.h:37
eap_packet_t * response
Packet we received from the peer.
Definition compose.h:48
eap_code_t code
Definition compose.h:35
uint8_t id
Definition compose.h:36
eap_packet_t * request
Packet we will send to the peer.
Definition compose.h:49
Contains a pair of request and response packets.
Definition compose.h:47
static size_t min(size_t x, size_t y)
Definition dbuff.c:66
#define fr_dbuff_used(_dbuff_or_marker)
Return the number of bytes remaining between the start of the dbuff or marker and the current positio...
Definition dbuff.h:819
#define fr_dbuff_out_memcpy(_out, _dbuff_or_marker, _outlen)
Copy exactly _outlen bytes from the dbuff.
Definition dbuff.h:1785
#define fr_dbuff_remaining(_dbuff_or_marker)
Return the number of bytes remaining between the dbuff or marker and the end of the buffer.
Definition dbuff.h:795
#define fr_dbuff_in_bytes(_dbuff_or_marker,...)
Copy a byte sequence into a dbuff or marker.
Definition dbuff.h:1518
#define fr_dbuff_in_memcpy_partial(_out, _in, _inlen)
Copy at most _inlen bytes into the dbuff.
Definition dbuff.h:1491
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:177
#define MEM(x)
Definition debug.h:38
unlang_action_t 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:278
static eap_tls_status_t eap_tls_verify(request_t *request, eap_session_t *eap_session)
Check that this EAP-TLS packet is correct and the progression of EAP-TLS packets is sane.
Definition tls.c:584
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:1215
static unlang_action_t eap_tls_handshake_push(request_t *request, eap_session_t *eap_session)
Push functions to continue the handshake asynchronously.
Definition tls.c:991
static int eap_tls_ack(request_t *request, eap_session_t *eap_session)
ACK a fragment of the TLS record from the peer.
Definition tls.c:484
void eap_tls_conf_check(CONF_SECTION *cs, fr_tls_conf_t *tls_conf, bool delayed_tickets)
Apply the limits that EAP puts on a parsed tls { ... } section.
Definition tls.c:1393
size_t eap_tls_status_table_len
Definition tls.c:94
int eap_tls_compose(request_t *request, eap_session_t *eap_session, eap_tls_status_t status, uint8_t flags, fr_dbuff_t *record, size_t record_len, size_t frag_len)
Convert the EAP-TLS reply packet into an EAP packet.
Definition tls.c:114
int eap_tls_start(request_t *request, eap_session_t *eap_session)
Send an initial EAP-TLS request to the peer.
Definition tls.c:242
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:392
#define SET_TLS_VERSION(_type)
int eap_tls_check_stateless(CONF_SECTION *cs, fr_tls_conf_t const *tls_conf)
Check that the TLS configuration does not need stateless session tickets.
Definition tls.c:1432
unlang_action_t eap_tls_fail(request_t *request, eap_session_t *eap_session)
Send an EAP-TLS failure.
Definition tls.c:339
USES_APPLE_DEPRECATED_API fr_table_num_ordered_t const eap_tls_status_table[]
Definition tls.c:80
static eap_tls_status_t eap_tls_session_status(request_t *request, eap_session_t *eap_session)
Reduce session states down into an easy to use status.
Definition tls.c:504
static unlang_action_t eap_tls_handshake_resume(request_t *request, void *uctx)
Process the result from the last TLS handshake round.
Definition tls.c:844
unlang_action_t eap_tls_process(request_t *request, eap_session_t *eap_session)
Process an EAP TLS request.
Definition tls.c:1040
Generic EAP over TLS API.
uint8_t data[]
Definition tls.h:119
int base_flags
Some protocols use the reserved bits of the EAP-TLS flags (such as PEAP).
Definition tls.h:135
eap_tls_status_t
Definition tls.h:93
@ EAP_TLS_RECORD_RECV_FIRST
Received first fragment of a record.
Definition tls.h:112
@ EAP_TLS_INVALID
Invalid, don't reply.
Definition tls.h:94
@ EAP_TLS_HANDLED
TLS code has handled it.
Definition tls.h:97
@ EAP_TLS_RECORD_RECV_MORE
Received additional fragment of a record.
Definition tls.h:113
@ EAP_TLS_ACK_SEND
Acknowledge receipt of a record or record fragment.
Definition tls.h:105
@ EAP_TLS_RECORD_SEND
We're sending a record.
Definition tls.h:104
@ EAP_TLS_RECORD_RECV_COMPLETE
Received final fragment of a record.
Definition tls.h:114
@ EAP_TLS_START_SEND
We're starting a new TLS session.
Definition tls.h:103
@ EAP_TLS_FAIL
Fail, send fail.
Definition tls.h:96
@ EAP_TLS_ESTABLISHED
Session established, send success (or start phase2).
Definition tls.h:95
eap_tls_status_t state
The state of the EAP-TLS session.
Definition tls.h:130
bool phase2
Whether we're in phase 2.
Definition tls.h:139
#define TLS_RESERVED1(x)
Definition tls.h:83
#define TLS_MORE_FRAGMENTS(x)
Definition tls.h:86
fr_tls_session_t * tls_session
TLS session used to authenticate peer or tunnel sensitive data.
Definition tls.h:132
bool record_in_started
Whether a record transfer from the peer is currently in progress.
Definition tls.h:150
size_t record_out_total_len
Actual/Total TLS message length we're sending.
Definition tls.h:148
#define SET_START(x)
Definition tls.h:89
#define TLS_RESERVED3(x)
Definition tls.h:81
#define SET_LENGTH_INCLUDED(x)
Definition tls.h:91
uint8_t flags
Definition tls.h:118
#define TLS_START(x)
Definition tls.h:85
size_t record_in_total_len
How long the peer indicated the complete tls record would be.
Definition tls.h:152
#define TLS_RESERVED0(x)
Definition tls.h:84
bool record_out_started
for methods with inner auth, if the inner auth succeeded.
Definition tls.h:146
size_t record_in_recvd_len
How much of the record we've received so far.
Definition tls.h:154
#define TLS_LENGTH_INCLUDED(x)
Definition tls.h:87
#define TLS_RESERVED2(x)
Definition tls.h:82
#define EAP_TLS_NESTED_OVERHEAD
Overhead subtracted from the MTU of an EAP-TLS session which is nested inside a tunneled method.
Definition tls.h:63
#define TLS_RESERVED4(x)
Definition tls.h:80
#define TLS_HEADER_LENGTH_FIELD_LEN
Definition tls.h:56
#define SET_MORE_FRAGMENTS(x)
Definition tls.h:90
bool authentication_success
Definition tls.h:144
bool include_length
A flag to include length in every TLS Data/Alert packet.
Definition tls.h:141
Tracks the state of an EAP-TLS session.
Definition tls.h:129
@ FR_EAP_METHOD_TTLS
Definition types.h:66
@ FR_EAP_METHOD_TLS
Definition types.h:58
size_t length
Definition types.h:111
#define EAP_HEADER_LEN
Definition types.h:34
uint8_t * data
Definition types.h:112
@ FR_EAP_CODE_FAILURE
Definition types.h:40
@ FR_EAP_CODE_REQUEST
Definition types.h:37
@ FR_EAP_CODE_SUCCESS
Definition types.h:39
#define unlang_function_push(_request, _func, _repeat, _signal, _sigmask, _top_frame, _uctx)
Push a generic function onto the unlang stack.
Definition function.h:181
void unlang_interpet_frame_discard(request_t *request)
Discard the bottom most frame on the request's stack.
Definition interpret.c:2751
#define UNLANG_SUB_FRAME
Definition interpret.h:37
HIDDEN fr_dict_attr_t const * attr_eap_identity
Definition base.c:89
HIDDEN fr_dict_attr_t const * attr_tls_min_version
Definition base.c:102
HIDDEN fr_dict_attr_t const * attr_framed_mtu
Definition base.c:97
HIDDEN fr_dict_attr_t const * attr_eap_session_id
Definition base.c:88
HIDDEN fr_dict_attr_t const * attr_tls_max_version
Definition base.c:103
HIDDEN fr_dict_attr_t const * attr_eap_type
Definition base.c:90
int eap_crypto_mppe_keys(request_t *request, SSL *ssl, eap_tls_prf_label_t *prf_label)
Generate keys according to RFC 5216 and add to the reply.
Definition crypto.c:83
int eap_crypto_tls_session_id(TALLOC_CTX *ctx, request_t *request, SSL *ssl, eap_tls_prf_label_t *prf_label, uint8_t **out, uint8_t eap_type)
Definition crypto.c:130
bool eap_session_in_tunnel(request_t const *request)
Check whether a request runs inside the tunnel of another EAP method.
Definition session.c:223
char * identity
NAI (User-Name) from EAP-Identity.
Definition session.h:56
void * opaque
Opaque data used by EAP methods.
Definition session.h:63
bool tls
Whether EAP method uses TLS.
Definition session.h:71
eap_type_t type
EAP method number.
Definition session.h:50
request_t * request
Current request.
Definition session.h:52
eap_round_t * this_round
The EAP response we're processing, and the EAP request we're building.
Definition session.h:60
eap_round_t * prev_round
Previous response/request pair.
Definition session.h:58
bool finished
Whether we consider this session complete.
Definition session.h:73
Tracks the progress of a single session of any EAP method.
Definition session.h:41
#define REXDENT()
Exdent (unindent) R* messages by one level.
Definition log.h:460
#define RDEBUG3(fmt,...)
Definition log.h:360
#define RERROR(fmt,...)
Definition log.h:315
#define RINDENT()
Indent R* messages by one level.
Definition log.h:447
unsigned int uint32_t
unsigned char uint8_t
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:716
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:284
int fr_pair_value_memdup_buffer_shallow(fr_pair_t *vp, uint8_t const *src, bool tainted)
Assign a talloced buffer to a "octets" type value pair.
Definition pair.c:2981
VQP attributes.
#define fr_assert(_expr)
Definition rad_assert.h:37
#define REDEBUG(fmt,...)
#define RDEBUG2(fmt,...)
static bool done
Definition radclient.c:80
static rs_t * conf
Definition radsniff.c:52
#define pair_delete_reply(_pair_or_da)
Delete a fr_pair_t in the reply list.
Definition pair.h:181
#define pair_append_reply(_attr, _da)
Allocate and append a fr_pair_t to reply list.
Definition pair.h:47
@ FR_SIGNAL_NONE
No signals.
Definition signal.h:39
fr_pair_value_bstrdup_buffer(vp, eap_session->identity, true)
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
Definition table.h:804
An element in an arbitrarily ordered array of name to num mappings.
Definition table.h:57
#define fr_time_delta_lt(_a, _b)
Definition time.h:285
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
Definition time.h:599
static fr_sbuff_err_t char size_t fr_sbuff_t size_t max
Definition value.h:1061
static fr_slen_t data
Definition value.h:1366
static fr_sbuff_err_t char size_t * len
Definition value.h:1061
#define fr_box_time_delta(_val)
Definition value.h:397