The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
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: b056c118b0b6f0707b6adedd23e5deb6f02e4143 $
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: b056c118b0b6f0707b6adedd23e5deb6f02e4143 $")
72USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */
73
74#include <freeradius-devel/unlang/function.h>
75#include <freeradius-devel/server/pair.h>
76#include "tls.h"
77#include "attrs.h"
78
80 { L("invalid"), EAP_TLS_INVALID },
81 { L("established"), EAP_TLS_ESTABLISHED },
82 { L("fail"), EAP_TLS_FAIL },
83 { L("handled"), EAP_TLS_HANDLED },
84
85 { L("start"), EAP_TLS_START_SEND },
86 { L("request"), EAP_TLS_RECORD_SEND },
87 { L("ack"), EAP_TLS_ACK_SEND },
88
89 { L("first"), EAP_TLS_RECORD_RECV_FIRST },
90 { L("more"), EAP_TLS_RECORD_RECV_MORE },
91 { L("complete"), EAP_TLS_RECORD_RECV_COMPLETE }
92};
94
95/** Convert the EAP-TLS reply packet into an EAP packet
96 *
97 * The EAP packet will be written to eap_round->request, with the original reply
98 * being untouched.
99 *
100 * @param[in] request The current subrequest.
101 * @param[in] eap_session to continue.
102 * @param[in] status What type of packet we're sending.
103 * @param[in] flags to set. This is checked to determine if
104 * we need to include a length field.
105 * @param[in] record The record buffer to read from. This
106 * most only be set for EAP_TLS_RECORD_SEND packets.
107 * @param[in] record_len the length of the record we're sending.
108 * @param[in] frag_len the length of the fragment we're sending.
109 * @return
110 * - 0 on success.
111 * - -1 on failure.
112 */
113int eap_tls_compose(request_t *request, eap_session_t *eap_session, eap_tls_status_t status, uint8_t flags,
114 fr_tls_record_t *record, size_t record_len, size_t frag_len)
115{
116 eap_round_t *eap_round = eap_session->this_round;
117 eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
118 fr_tls_session_t *tls_session = eap_tls_session->tls_session;
119 uint8_t *p;
120 size_t len = 1; /* Flags */
121
122 fr_assert(request->parent); /* must be a subrequest */
123
124 /*
125 * First output the flags (for debugging)
126 */
127 RDEBUG3("Setting flags %c%c%c%c%c%c%c%c",
128 TLS_START(flags) ? 'S' : '-',
129 TLS_MORE_FRAGMENTS(flags) ? 'M' : '-',
130 TLS_LENGTH_INCLUDED(flags) ? 'L' : '-',
131 TLS_RESERVED0(flags) ? 'R' : '-',
132 TLS_RESERVED1(flags) ? 'R' : '-',
133 TLS_RESERVED2(flags) ? 'R' : '-',
134 TLS_RESERVED3(flags) ? 'R' : '-',
135 TLS_RESERVED4(flags) ? 'R' : '-');
136
137 /*
138 * Determine the length (sans header) of our EAP-TLS
139 * packet. The reason for not including the length is
140 * that the fields are the same as normal EAP messages.
141 */
142 switch (status) {
144 if (TLS_LENGTH_INCLUDED(flags)) len += TLS_HEADER_LENGTH_FIELD_LEN; /* TLS record length field */
145 if (record) len += frag_len;
146 break;
147
149 if (record_len != 0) len += frag_len;
150 break;
151
152 default:
153 break;
154 }
155
156 /*
157 * When the EAP server receives an EAP-Response with the
158 * M bit set, it MUST respond with an EAP-Request with
159 * EAP-Type = EAP-TLS and no data. This serves as a
160 * fragment ACK. The EAP peer MUST wait until it receives
161 * the EAP-Request before sending another fragment.
162 *
163 * In order to prevent errors in the processing of
164 * fragments, the EAP server MUST use increment the
165 * Identifier value for each fragment ACK contained
166 * within an EAP-Request, and the peer MUST include this
167 * Identifier value in the subsequent fragment contained
168 * within an EAP-Reponse.
169 */
170 eap_round->request->type.data = p = talloc_array(eap_round->request, uint8_t, len);
171 if (!p) return -1;
172 eap_round->request->type.length = len;
173
174 *p++ = flags;
175
176 if (TLS_LENGTH_INCLUDED(flags)) {
177 uint32_t net_record_len;
178
179 /*
180 * If we need to add the length field,
181 * convert the total record length to
182 * network byte order and copy it in at the
183 * start of the packet.
184 */
185 net_record_len = htonl(record_len);
186 memcpy(p, &net_record_len, sizeof(net_record_len));
187 p += sizeof(net_record_len);
188 }
189
190 if (record) tls_session->record_to_buff(record, p, frag_len);
191
192 switch (status) {
193 case EAP_TLS_ACK_SEND:
196 eap_round->request->code = FR_EAP_CODE_REQUEST;
197 break;
198
200 eap_round->request->code = FR_EAP_CODE_SUCCESS;
201 break;
202
203 case EAP_TLS_FAIL:
204 eap_round->request->code = FR_EAP_CODE_FAILURE;
205 break;
206
207 default:
208 /* Should never enter here */
209 fr_assert(0);
210 break;
211 }
212
213 return 0;
214}
215
216/** Send an initial EAP-TLS request to the peer.
217 *
218 * Once having received the peer's Identity, the EAP server MUST respond with an
219 * EAP-TLS/Start packet, which is an EAP-Request packet with EAP-Type = EAP-TLS,
220 * the Start (S) bit set, and no data.
221 *
222 * The EAP-TLS conversation will then begin, with the peer sending an EAP-Response
223 * packet with EAP-Type = EAP-TLS. The data field of that packet will be the TLS data.
224 *
225 * The S flag is set only within the EAP-TLS start message sent from the EAP server to the peer.
226 *
227 * - len = header + type + tls_typedata
228 * - tls_typedata = flags(Start (S) bit set, and no data)
229 *
230 * Fragment length is Framed-MTU - 4.
231 *
232 * @param[in] request The current subrequest.
233 * @param[in] eap_session to initiate.
234 * @return
235 * - 0 on success.
236 * - -1 on failure.
237 */
238int eap_tls_start(request_t *request, eap_session_t *eap_session)
239{
240 eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
241
242 fr_assert(request->parent); /* must be a subrequest */
243
244 return eap_tls_compose(request, eap_session, EAP_TLS_START_SEND,
245 SET_START(eap_tls_session->base_flags), NULL, 0, 0);
246}
247
248/** Send an EAP-TLS success
249 *
250 * Composes an EAP-TLS-Success. This is a message with code EAP_TLS_ESTABLISHED.
251 * It contains no cryptographic material, and is not protected.
252 *
253 * We add the MPPE keys here. These are used by the NAS. The supplicant
254 * will derive the same keys separately.
255 *
256 * @param[in] request The current subrequest.
257 * @param[in] eap_session that completed successfully.
258 * @param[in] prf_label PRF label struct
259 * @return
260 * - 0 on success.
261 * - -1 on failure.
262 */
263int eap_tls_success(request_t *request, eap_session_t *eap_session, eap_tls_prf_label_t *prf_label)
264{
265 eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
266 fr_tls_session_t *tls_session = eap_tls_session->tls_session;
267
268 fr_assert(request->parent); /* must be a subrequest */
269
270 eap_session->finished = true;
271
272 /*
273 * Build the success packet
274 */
275 if (eap_tls_compose(request, eap_session, EAP_TLS_ESTABLISHED,
276 eap_tls_session->base_flags, NULL, 0, 0) < 0) return -1;
277
278 if (!prf_label) return 0;
279
280 /*
281 * Automatically generate MPPE keying material.
282 */
283 if (eap_crypto_mppe_keys(request->parent, tls_session->ssl, prf_label) < 0) return -1;
284
285 /*
286 * Add the EAP session ID to the request
287 */
288 {
289 uint8_t *session_id;
290 fr_pair_t *vp;
291
293 if (eap_crypto_tls_session_id(vp, request, tls_session->ssl, prf_label,
294 &session_id, eap_session->type) < 0) {
296 return -1;
297 }
298 fr_pair_value_memdup_buffer_shallow(vp, session_id, false);
299
300 RINDENT();
301 RDEBUG2("reply.%pP", vp);
302 REXDENT();
303 }
304
305 return 0;
306}
307
308/** Send an EAP-TLS failure
309 *
310 * Composes an EAP-TLS-Failure. This is a message with code EAP_TLS_FAILURE.
311 * It contains no cryptographic material, and is not protected.
312 *
313 * In addition to sending the failure, will destroy any cached session data.
314 *
315 * @param[in] request The current subrequest.
316 * @param[in] eap_session that failed.
317 * @return
318 * - 0 on success.
319 * - -1 on failure (to compose a valid packet).
320 */
321int eap_tls_fail(request_t *request, eap_session_t *eap_session)
322{
323 eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
324 fr_tls_session_t *tls_session = eap_tls_session->tls_session;
325
326 fr_assert(request->parent); /* must be a subrequest */
327
328 eap_session->finished = true;
329
330 /*
331 * Destroy any cached session data
332 */
333 fr_tls_cache_deny(request, tls_session);
334
335 if (eap_tls_compose(request, eap_session, EAP_TLS_FAIL,
336 eap_tls_session->base_flags, NULL, 0, 0) < 0) return -1;
337 return 0;
338}
339
340/** Frames the OpenSSL data that needs to be sent to the client in an EAP-Request
341 *
342 * A single TLS record may be up to 16384 octets in length, but a TLS message
343 * may span multiple TLS records, and a TLS certificate message may theoretically,
344 * be as big as 16MB.
345 *
346 * In EAP-TLS with no inner method, this is used primarily to send our certificate
347 * chain to the peer.
348 *
349 * In other methods this function is also called to package up application data
350 * for the inner tunnel method.
351 *
352 * The eap_tls_session->length_included flag determines whether we include the extra
353 * four byte length field in the request and set the L flag.
354 *
355 * If present, the tls_length field indicates the total length of the reassembled
356 * TLS record.
357 *
358 * If eap_tls_session->length_included this means we include L flag and the tls_length
359 * field in EVERY packet we send out.
360 *
361 * If !eap_tls_session->length_included this means we include L flag and tls_length
362 * field **ONLY** in First packet of a fragment series. We do not use it anywhere
363 * else.
364 *
365 * @param request the request
366 * @param eap_session that's continuing.
367 * @return
368 * - 0 on success.
369 * - -1 on failure.
370 */
371int eap_tls_request(request_t *request, eap_session_t *eap_session)
372{
373 eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
374 fr_tls_session_t *tls_session = eap_tls_session->tls_session;
375 uint8_t flags = eap_tls_session->base_flags;
376 size_t frag_len;
377 bool length_included;
378
379 /*
380 * We don't need to always include the length
381 * (just in the first fragment) but it is
382 * configurable for compatibility.
383 */
384 length_included = eap_tls_session->include_length;
385
386 /*
387 * If this is the first fragment, record the complete
388 * TLS record length.
389 */
390 if (eap_tls_session->record_out_started == false) {
391 eap_tls_session->record_out_total_len = tls_session->dirty_out.used;
392 }
393
394 /*
395 * If the data we're sending is greater than the MTU
396 * then we need to fragment it.
397 */
398 if ((tls_session->dirty_out.used +
399 (length_included ? TLS_HEADER_LENGTH_FIELD_LEN : 0)) > tls_session->mtu) {
400 if (eap_tls_session->record_out_started == false) length_included = true;
401
402 frag_len = length_included ? tls_session->mtu - TLS_HEADER_LENGTH_FIELD_LEN:
403 tls_session->mtu;
404
405 flags = SET_MORE_FRAGMENTS(flags);
406
407 /*
408 * Length MUST be included if we're record_out_started
409 * and this is the first fragment.
410 */
411 if (eap_tls_session->record_out_started == false) {
412 RDEBUG2("Complete TLS record (%zu bytes) larger than MTU (%zu bytes), will fragment",
413 eap_tls_session->record_out_total_len, frag_len); /* frag_len is correct here */
414 RDEBUG2("Sending first TLS record fragment (%zu bytes), %zu bytes remaining",
415 frag_len, tls_session->dirty_out.used - frag_len);
416 } else {
417 RDEBUG2("Sending additional TLS record fragment (%zu bytes), %zu bytes remaining",
418 frag_len, tls_session->dirty_out.used - frag_len);
419 }
420 eap_tls_session->record_out_started = true; /* Start a new series of fragments */
421 /*
422 * Otherwise, we're either sending a record smaller
423 * than the MTU or this is the final fragment.
424 */
425 } else {
426 frag_len = tls_session->dirty_out.used; /* Remaining data to drain */
427
428 if (eap_tls_session->record_out_started == false) {
429 RDEBUG2("Sending complete TLS record (%zu bytes)", frag_len);
430 } else {
431 RDEBUG2("Sending final TLS record fragment (%zu bytes)", frag_len);
432 }
433 eap_tls_session->record_out_started = false;
434 }
435
436 /*
437 * Update the flags to say we're including the
438 * TLS record length.
439 */
440 if (length_included) flags = SET_LENGTH_INCLUDED(flags);
441
442 return eap_tls_compose(request, eap_session, EAP_TLS_RECORD_SEND, flags,
443 &tls_session->dirty_out, eap_tls_session->record_out_total_len, frag_len);
444}
445
446/** ACK a fragment of the TLS record from the peer
447 *
448 * EAP server sends an ACK when it determines there are More fragments to
449 * receive to make the complete TLS-record.
450 *
451 * When the EAP server receives an EAP-Response with the M bit set, it MUST
452 * respond with an EAP-Request with EAP-Type = EAP-TLS and no data. This serves
453 * as a fragment ACK.
454 *
455 * In order to prevent errors in the processing of fragments, the EAP server
456 * MUST use increment the Identifier value for each fragment ACK contained
457 * within an EAP-Request, and the peer MUST include this Identifier value in
458 * the subsequent fragment contained within an EAP-Reponse.
459 *
460 * @param[in] request The current subrequest.
461 * @param[in] eap_session that we're acking the fragment for.
462 */
463static int eap_tls_ack(request_t *request, eap_session_t *eap_session)
464{
465 eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
466
467 fr_assert(request->parent); /* must be a subrequest */
468
469 RDEBUG2("ACKing Peer's TLS record fragment");
470 return eap_tls_compose(request, eap_session, EAP_TLS_ACK_SEND,
471 eap_tls_session->base_flags, NULL, 0, 0);
472}
473
474/** Reduce session states down into an easy to use status
475 *
476 * @param[in] request The current subrequest.
477 * @param[in] eap_session that we're acking the fragment for.
478 * @return
479 * - EAP_TLS_ESTABLISHED - Handshake completed.
480 * - EAP_TLS_FAIL - Fatal alert from the client.
481 * - EAP_TLS_RECORD_SEND - Need more data, or previous fragment was acked.
482 */
484{
485 eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
486 fr_tls_session_t *tls_session = eap_tls_session->tls_session;
487
488 if (tls_session == NULL){
489 REDEBUG("Unexpected ACK received: No ongoing SSL tls_session");
490 return EAP_TLS_INVALID;
491 }
492 if (!tls_session->info.initialized) {
493 RDEBUG2("No SSL info available. Waiting for more SSL data");
494 return EAP_TLS_RECORD_SEND;
495 }
496
497 if ((tls_session->info.content_type == SSL3_RT_HANDSHAKE) &&
498 (tls_session->info.origin == TLS_INFO_ORIGIN_RECORD_RECEIVED)) {
499 REDEBUG("Unexpected ACK received: We sent no previous messages");
500 return EAP_TLS_INVALID;
501 }
502
503 switch (tls_session->info.content_type) {
504 case SSL3_RT_ALERT:
505 RDEBUG2("Peer ACKed our alert");
506 return EAP_TLS_FAIL;
507
508 case SSL3_RT_HANDSHAKE:
509 if (SSL_is_init_finished(tls_session->ssl) && (tls_session->dirty_out.used == 0)) {
510 RDEBUG2("Peer ACKed our handshake fragment. handshake is finished");
511
512 /*
513 * From now on all the content is
514 * application data set it here as nobody else
515 * sets it.
516 */
517 tls_session->info.content_type = SSL3_RT_APPLICATION_DATA;
518 return EAP_TLS_ESTABLISHED;
519 } /* else more data to send */
520
521 RDEBUG2("Peer ACKed our handshake fragment");
522 /* Fragmentation handler, send next fragment */
523 return EAP_TLS_RECORD_SEND;
524
525 case SSL3_RT_APPLICATION_DATA:
526 RDEBUG2("Peer ACKed our application data fragment");
527 return EAP_TLS_RECORD_SEND;
528
529 /*
530 * For the rest of the conditions, switch over
531 * to the default section below.
532 */
533 default:
534 /*
535 * If the last message was from us, then the session is established
536 */
537 if (tls_session->info.origin == TLS_INFO_ORIGIN_RECORD_SENT) return EAP_TLS_ESTABLISHED;
538 REDEBUG("Invalid ACK received: %d", tls_session->info.content_type);
539 return EAP_TLS_INVALID;
540 }
541}
542
543/** Check that this EAP-TLS packet is correct and the progression of EAP-TLS packets is sane
544 *
545 * @note In the received packet, No data will be present in case of ACK or NAK
546 * in this case the packet->data pointer will be NULL.
547 *
548 * @param[in] request the current subrequest.
549 * @param[in] eap_session the current EAP session state.
550 * @return
551 * - EAP_TLS_INVALID if the TLS record or progression is invalid.
552 * - EAP_TLS_FAIL handshake failed.
553 * - EAP_TLS_RECORD_RECV_FIRST this is the start of a new sequence of record fragments.
554 * - EAP_TLS_RECORD_RECV_MORE this is a continuation of a sequence of fragments.
555 * - EAP_TLS_RECORD_RECV_COMPLETE we received a completed record.
556 * - EAP_TLS_RECORD_SEND send more data to peer.
557 * - EAP_TLS_ESTABLISHED handshake is complete, TLS session has been established.
558 */
560{
561 eap_round_t *this_round = eap_session->this_round;
562 eap_round_t *prev_round = eap_session->prev_round;
563 eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
564
565 eap_tls_data_t *eap_tls_data;
566 size_t frag_len, header_len;
567
568 fr_assert(request->parent); /* must be a subrequest */
569
570 /*
571 * All EAP-TLS packets must contain type and flags fields.
572 */
573 if (this_round->response->length < (EAP_HEADER_LEN + 2)) {
574 REDEBUG("Invalid EAP-TLS packet: Expected at least %zu bytes got %zu bytes",
575 (size_t)EAP_HEADER_LEN + 2, this_round->response->length);
576 return EAP_TLS_INVALID;
577 }
578
579 /*
580 * We don't check ANY of the input parameters. It's all
581 * code which works together, so if something is wrong,
582 * we SHOULD core dump.
583 *
584 * e.g. if this_round is NULL, or if this_round->response is
585 * NULL, or if it's NOT an EAP-Response, or if the packet
586 * is too short. See eap_validate()., in ../../eap.c
587 */
588 eap_tls_data = (eap_tls_data_t *)this_round->response->type.data;
589 if (!eap_tls_data) {
590 REDEBUG("Invalid EAP-TLS packet; no data");
591 return EAP_TLS_INVALID;
592 }
593
594 /*
595 * First output the flags (for debugging)
596 */
597 RDEBUG3("Peer sent flags %c%c%c%c%c%c%c%c",
598 TLS_START(eap_tls_data->flags) ? 'S' : '-',
599 TLS_MORE_FRAGMENTS(eap_tls_data->flags) ? 'M' : '-',
600 TLS_LENGTH_INCLUDED(eap_tls_data->flags) ? 'L' : '-',
601 TLS_RESERVED0(eap_tls_data->flags) ? 'R' : '-',
602 TLS_RESERVED1(eap_tls_data->flags) ? 'R' : '-',
603 TLS_RESERVED2(eap_tls_data->flags) ? 'R' : '-',
604 TLS_RESERVED3(eap_tls_data->flags) ? 'R' : '-',
605 TLS_RESERVED4(eap_tls_data->flags) ? 'R' : '-');
606
607 /*
608 * This length includes the type and flags field and
609 * the message length field if the flags indicate it's present.
610 */
611 header_len = EAP_HEADER_LEN + (TLS_LENGTH_INCLUDED(eap_tls_data->flags) ? 6 : 2);
612 if (this_round->response->length < header_len) {
613 REDEBUG("Invalid EAP-TLS packet: Expected at least %zu bytes got %zu bytes",
614 header_len, this_round->response->length);
615 return EAP_TLS_INVALID;
616 }
617
618 /*
619 * check for ACK
620 *
621 * If there's no TLS data, or there's 1 byte of TLS data,
622 * with the flags set to zero, then it's an ACK.
623 *
624 * Find if this is a reply to the previous request sent
625 */
626 if ((this_round->response->length == EAP_HEADER_LEN + 2) &&
627 ((eap_tls_data->flags & 0xc0) == 0x00)) {
628 if (!prev_round || (prev_round->request->id != this_round->response->id)) {
629 REDEBUG("Received Invalid TLS ACK");
630 return EAP_TLS_INVALID;
631 }
632 return eap_tls_session_status(request, eap_session);
633 }
634
635 /*
636 * We send TLS_START, but do not receive it.
637 */
638 if (TLS_START(eap_tls_data->flags)) {
639 REDEBUG("Peer sent EAP-TLS Start message (only the server is allowed to do this)");
640 return EAP_TLS_INVALID;
641 }
642
643 /*
644 * Calculate this fragment's length
645 */
646 frag_len = this_round->response->length - header_len;
647
648 /*
649 * This fragment has no data, but the header says that there is more data!
650 */
651 if (!frag_len && TLS_MORE_FRAGMENTS(eap_tls_data->flags)) {
652 REDEBUG("Peer sent EAP-TLS with zero-length fragment and 'more' bit set - if there is no data, there should not be more!");
653 return EAP_TLS_INVALID;
654 }
655
656 /*
657 * The L bit (length included) is set to indicate the
658 * presence of the four octet TLS Message Length field,
659 * and MUST be set for the first fragment of a fragmented
660 * TLS message or set of messages.
661 *
662 * The M bit (more fragments) is set on all but the last
663 * fragment.
664 *
665 * The S bit (EAP-TLS start) is set in an EAP-TLS Start
666 * message. This differentiates the EAP-TLS Start message
667 * from a fragment acknowledgement.
668 */
669 if (TLS_LENGTH_INCLUDED(eap_tls_data->flags)) {
670 size_t total_len;
671
672 if (eap_tls_data->data[0] || eap_tls_data->data[1]) {
673 REDEBUG("TLS record length is > 65536");
674 return EAP_TLS_INVALID;
675 }
676
677 total_len = eap_tls_data->data[2] * 256 | eap_tls_data->data[3];
678 if (frag_len > total_len) {
679 REDEBUG("TLS fragment length (%zu bytes) greater than TLS record length (%zu bytes)",
680 frag_len, total_len);
681 return EAP_TLS_INVALID;
682 }
683
684 if (total_len > FR_TLS_MAX_RECORD_SIZE) {
685 REDEBUG("Reassembled TLS record will be %zu bytes, "
686 "greater than our maximum record size (" STRINGIFY(FR_TLS_MAX_RECORD_SIZE) " bytes)",
687 total_len);
688 return EAP_TLS_INVALID;
689 }
690
691 /*
692 * wpa_supplicant's implementation of PEAPv0, and likely other
693 * implementations of PEAPv0 will always include a Length flag
694 * for every record fragment if performing mutual TLS auth.
695 *
696 * If the eap_session says this is not the first fragment, then
697 * don't count this as a new record, and continue as if we
698 * hadn't seen the length flag.
699 */
700 if (eap_tls_session->record_in_started) goto ignore_length;
701
702 /*
703 * This is the first fragment of a fragmented TLS record transfer.
704 */
705 RDEBUG2("Peer indicated complete TLS record size will be %zu bytes", total_len);
706 if (TLS_MORE_FRAGMENTS(eap_tls_data->flags)) {
707 /*
708 * The peer is free to send fragments of wildly varying
709 * lengths, but the vast majority won't.
710 *
711 * In this calculation we take into account the fact that the future
712 * fragments are likely to be 4 bytes larger than the initial one
713 * as they won't contain the length field.
714 */
715 if (frag_len + 4) { /* check for wrap, else clang scan gets excited */
716 RDEBUG2("Expecting %i TLS record fragments",
717 (int)((((total_len - frag_len) + ((frag_len + 4) - 1)) / (frag_len + 4)) + 1));
718 }
719
720 /*
721 * First fragment. record_in_started bool was false,
722 * and we received a length included + more fragments packet.
723 */
724 RDEBUG2("Got first TLS record fragment (%zu bytes). Peer indicated more fragments "
725 "to follow", frag_len);
726 eap_tls_session->record_in_total_len = total_len;
727 eap_tls_session->record_in_recvd_len = frag_len;
728 eap_tls_session->record_in_started = true;
729
731 }
732
733 /*
734 * Else this is the complete TLS record.
735 */
736 if (total_len != frag_len) {
737 REDEBUG("Peer indicated no more fragments, but TLS record length (%zu bytes) "
738 "does not match EAP-TLS data length (%zu bytes)", total_len, frag_len);
739 return EAP_TLS_INVALID;
740 }
741
742 /*
743 * RFC5216 doesn't specify explicitly whether a non-fragmented
744 * packet should include the length or not.
745 *
746 * We support both options for maximum compatibility.
747 */
748 RDEBUG2("Got complete TLS record, with length field (%zu bytes)", frag_len);
750 }
751
752ignore_length:
753 if (TLS_MORE_FRAGMENTS(eap_tls_data->flags)) {
754 /*
755 * If this is not an ongoing transfer, and we have the M flag
756 * then this record transfer is invalid.
757 */
758 if (!eap_tls_session->record_in_started) {
759 REDEBUG("TLS More (M) flag set, but no fragmented record transfer was in progress");
760 return EAP_TLS_INVALID;
761 }
762
763 /*
764 * If this is an ongoing transfer, and we have the M flag,
765 * then this is just an additional fragment.
766 */
767 RDEBUG2("Got additional TLS record fragment (%zu bytes). Peer indicated more fragments to follow",
768 frag_len);
769 eap_tls_session->record_in_recvd_len += frag_len;
770 if (eap_tls_session->record_in_recvd_len > eap_tls_session->record_in_total_len) {
771 REDEBUG("Total received TLS record fragments (%zu bytes), exceeds "
772 "indicated TLS record length (%zu bytes)",
773 eap_tls_session->record_in_recvd_len, eap_tls_session->record_in_total_len);
774 return EAP_TLS_INVALID;
775 }
777 }
778
779 /*
780 * No L flag and no M flag. This is either the final fragment,
781 * or a new transfer that was not started with a L flag, which
782 * RFC5216 hints, may be acceptable.
783 *
784 * If it's an in-progress record transfer, check we now have
785 * the complete record.
786 */
787 if (eap_tls_session->record_in_started) {
788 eap_tls_session->record_in_started = false;
789
790 RDEBUG2("Got final TLS record fragment (%zu bytes)", frag_len);
791 eap_tls_session->record_in_recvd_len += frag_len;
792 if (eap_tls_session->record_in_recvd_len != eap_tls_session->record_in_total_len) {
793 REDEBUG("Total received TLS record fragments (%zu bytes), does not equal indicated "
794 "TLS record length (%zu bytes)",
795 eap_tls_session->record_in_recvd_len, eap_tls_session->record_in_total_len);
796 return EAP_TLS_INVALID;
797 }
799 }
800
801 /*
802 * None of the flags are set, it wasn't an in progress transfer,
803 * but it's still a valid EAP-TLS packet.
804 */
805 RDEBUG2("Got complete TLS record (%zu bytes)", frag_len);
806
808}
809
810/** Process the result from the last TLS handshake round
811 *
812 * @return
813 * - eap_tls_session->state == EAP_TLS_FAIL if the message is invalid.
814 * - eap_tls_session->state == EAP_TLS_HANDLED if we need to send an
815 * additional request to the peer.
816 * - eap_tls_session->state == EAP_TLS_ESTABLISHED if the handshake
817 * completed successfully, and there's no more data to send.
818 */
820{
821 eap_session_t *eap_session = talloc_get_type_abort(uctx, eap_session_t);
822 eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
823 fr_tls_session_t *tls_session = talloc_get_type_abort(eap_tls_session->tls_session, fr_tls_session_t);
825
826 switch (tls_session->result) {
827 case FR_TLS_RESULT_IN_PROGRESS:
828 default:
829 fr_assert(0); /* Shouldn't have been called */
830 goto fail;
831
832 case FR_TLS_RESULT_ERROR:
833 REDEBUG("TLS receive handshake failed during operation");
834 goto fail;
835
836 case FR_TLS_RESULT_SUCCESS:
837 break;
838 }
839
840#ifdef TLS1_3_VERSION
841 /*
842 * https://tools.ietf.org/html/draft-ietf-emu-eap-tls13#section-2.5
843 *
844 * We need to signal the other end that TLS negotiation
845 * is done. We can't send a zero-length application data
846 * message, so we send application data which is one byte
847 * of zero.
848 *
849 * Note this is only done for when there is no application
850 * data to be sent. So this is done always for EAP-TLS but
851 * notibly not for PEAP even on resumption.
852 *
853 * We only want to send this application data IF:
854 *
855 * * EAP-TLS / TTLS / PEAP - session was resumed
856 * * EAP-TLS
857 * * SSL init is finished (presumed to be checked elsewhere)
858 * * we saw the client cert
859 * * OR we're using unauthenticated EAP-TLS where
860 * the administrator has decided to not ask for
861 * the client cert
862 */
863 if ((tls_session->info.version == TLS1_3_VERSION) &&
864 (tls_session->client_cert_ok || eap_tls_session->authentication_success || SSL_session_reused(tls_session->ssl))) {
865 if ((eap_session->type == FR_EAP_METHOD_TLS) || SSL_session_reused(tls_session->ssl)) {
866 eap_tls_session->authentication_success = true;
867
868 RDEBUG("(TLS) EAP Sending final Commitment Message.");
869 tls_session->record_from_buff(&tls_session->clean_in, "\0", 1);
870 } else {
871
872 /*
873 * Returns UNLANG_ACTION_PUSHED_CHILD unless something has failed
874 */
875 ret = fr_tls_session_async_handshake_push(request, tls_session);
876 if (ret != UNLANG_ACTION_FAIL) return ret;
877
878 REDEBUG("TLS receive handshake failed during operation");
879 goto fail;
880 }
881 }
882#endif
883
884 /*
885 * FIXME: return success/fail.
886 *
887 * TLS proper can decide what to do, then.
888 */
889 if (tls_session->dirty_out.used > 0) {
890 if (eap_tls_request(request, eap_session) < 0) {
891 REDEBUG("TLS failed composing a response");
892 goto fail;
893 }
894 eap_tls_session->state = EAP_TLS_HANDLED;
896 }
897
898 /*
899 * If there is no data to send i.e dirty_out.used <=0 and
900 * if the SSL handshake is finished, then return
901 * EAP_TLS_ESTABLISHED.
902 *
903 * For EAP-TLS this translates to an EAP-Success, for others
904 * this begins phase2.
905 */
906 if (eap_tls_session->phase2 || SSL_is_init_finished(tls_session->ssl)) {
907 eap_tls_session->phase2 = true;
908
909 /*
910 * Init is finished. The rest is
911 * application data.
912 */
913 tls_session->info.content_type = SSL3_RT_APPLICATION_DATA;
914 eap_tls_session->state = EAP_TLS_ESTABLISHED;
916 }
917
918 /*
919 * Who knows what happened...
920 */
921 REDEBUG("TLS failed during operation");
922fail:
923 fr_tls_cache_deny(request, tls_session);
924 eap_tls_session->state = EAP_TLS_FAIL;
925
927}
928
929/** Push functions to continue the handshake asynchronously
930 *
931 * @param[in] request the current subrequest.
932 * @param[in] eap_session to continue.
933 * @return
934 * - UNLANG_ACTION_PUSHED_CHILD
935 */
936static inline CC_HINT(always_inline) unlang_action_t eap_tls_handshake_push(request_t *request, eap_session_t *eap_session)
937{
938 eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
939 fr_tls_session_t *tls_session = talloc_get_type_abort(eap_tls_session->tls_session, fr_tls_session_t);
940
941 /*
942 * Will run after the handshake round completes
943 */
944 if (unlang_function_push(request,
945 NULL,
947 NULL,
949 eap_session) < 0) return UNLANG_ACTION_FAIL;
950
951 if (fr_tls_session_async_handshake_push(request, tls_session) < 0) return UNLANG_ACTION_FAIL;
952
954}
955
956/** Process an EAP TLS request
957 *
958 * Here we implement a basic state machine. The state machine is implicit and
959 * is driven by the state of the TLS session and the flags sent.
960 * INCOMING DATA:
961 * 1. EAP-TLS should get the complete TLS data from the peer.
962 * 2. Store that data in a data structure with any other required info
963 * 3. Hand this data structure to the TLS module.
964 * 4. TLS module will perform its operations on the data and hands back to EAP-TLS
965 * OUTGOING DATA:
966 * 1. EAP-TLS if necessary will fragment it and send it to the destination.
967 *
968 * During EAP-TLS initialization, TLS Context object will be initialised and stored.
969 * For every new authentication request, TLS will open a new session object and that
970 * session object SHOULD be maintained even after the session is completed, for session
971 * resumption.
972 *
973 * Note that we never return FAIL to the interpreter. Instead, we
974 * send the EAP failure back to the supplicant.
975 *
976 * @param request the request
977 * @param eap_session to continue.
978 * @return
979 * - UNLANG_ACTION_CALCULATE_RESULT
980 */
982{
983 eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
984 fr_tls_session_t *tls_session = eap_tls_session->tls_session;
985
986 eap_round_t *this_round = eap_session->this_round;
987
988 eap_tls_data_t *eap_tls_data;
989 uint8_t *data;
990 size_t data_len;
991
992 fr_assert(request->parent); /* must be a subrequest */
993
994 RDEBUG2("Continuing EAP-TLS");
995
996 /*
997 * Call eap_tls_verify to sanity check the incoming EAP data.
998 */
999 eap_tls_session->state = eap_tls_verify(request, eap_session);
1000 switch (eap_tls_session->state) {
1001 case EAP_TLS_INVALID:
1002 case EAP_TLS_FAIL:
1003 REDEBUG("[eap-tls verify] = %s", fr_table_str_by_value(eap_tls_status_table, eap_tls_session->state, "<INVALID>"));
1004 break;
1005
1006 default:
1007 RDEBUG2("[eap-tls verify] = %s", fr_table_str_by_value(eap_tls_status_table, eap_tls_session->state, "<INVALID>"));
1008 break;
1009 }
1010
1011 /*
1012 * Status in this here means 'state'. Our state is determined passively
1013 * for EAP-TLS, based on what state OpenSSL reported the TLS session
1014 * to be in, and what flags were last received from the peer.
1015 */
1016 switch (eap_tls_session->state) {
1017 /*
1018 * We've received a complete TLS record, this is the same as receiving a
1019 * fragment, except we also process the complete record.
1020 */
1022 /*
1023 * We've received a fragment of a TLS record
1024 *
1025 * Determine where the TLS record starts.
1026 *
1027 * If the length included flag is set, we need to skip over the 4 byte
1028 * message length field.
1029 *
1030 * Next - Copy the fragment data into OpenSSL's dirty in buffer so that it
1031 * can process it in a later call.
1032 */
1035 eap_tls_data = (eap_tls_data_t *)this_round->response->type.data;
1036 if (TLS_LENGTH_INCLUDED(eap_tls_data->flags)) {
1037 data = (this_round->response->type.data + 5); /* flags + TLS-Length */
1038 data_len = this_round->response->type.length - 5; /* flags + TLS-Length */
1039 } else {
1040 data = this_round->response->type.data + 1; /* flags */
1041 data_len = this_round->response->type.length - 1; /* flags */
1042 }
1043
1044 /*
1045 * Update the dirty_in buffer (data for reading by OpenSSL)
1046 *
1047 * This buffer will contain partial data when M bit is set, and should
1048 * should only be reinitialized when M bit is not set.
1049 */
1050 if ((tls_session->record_from_buff)(&tls_session->dirty_in, data, data_len) != data_len) {
1051 REDEBUG("Exceeded maximum record size");
1052 eap_tls_session->state = EAP_TLS_FAIL;
1053 goto done;
1054 }
1055
1056 /*
1057 * ACK fragments until we get a complete TLS record.
1058 */
1059 if (eap_tls_session->state != EAP_TLS_RECORD_RECV_COMPLETE) {
1060 if (eap_tls_ack(request, eap_session) < 0) {
1061 eap_tls_session->state = EAP_TLS_FAIL;
1062 } else {
1063 eap_tls_session->state = EAP_TLS_HANDLED;
1064 }
1065 goto done;
1066 }
1067
1068 /*
1069 * We have a complete record. If the handshake is finished
1070 * process it as application data, otherwise continue
1071 * the handshake.
1072 */
1073 if (eap_tls_session->phase2 || SSL_is_init_finished(tls_session->ssl)) {
1074 int ret;
1075
1076 eap_tls_session->phase2 = true;
1077
1078 ret = fr_tls_session_recv(request, tls_session);
1079 switch (ret) {
1080 case 0:
1081 eap_tls_session->state = EAP_TLS_RECORD_RECV_COMPLETE;
1082 break;
1083
1084 case 1:
1085 eap_tls_session->state = EAP_TLS_RECORD_RECV_MORE;
1086 break;
1087
1088 default:
1089 eap_tls_session->state = EAP_TLS_FAIL;
1090 break;
1091 }
1092 } else {
1093 /*
1094 * Asynchronously process more handshake data
1095 */
1096 return eap_tls_handshake_push(request, eap_session);
1097 }
1098 break;
1099 /*
1100 * We have fragments or records to send to the peer
1101 */
1103 /*
1104 * Return a "yes we're done" if there's no more data to send,
1105 * and we've just managed to finish the SSL session initialization.
1106 */
1107 if (!eap_tls_session->phase2 && (tls_session->dirty_out.used == 0) &&
1108 SSL_is_init_finished(tls_session->ssl)) {
1109 eap_tls_session->phase2 = true;
1110 eap_tls_session->state = EAP_TLS_ESTABLISHED;
1111 goto done;
1112 }
1113
1114 if (eap_tls_request(request, eap_session) < 0) {
1115 eap_tls_session->state = EAP_TLS_FAIL;
1116 } else {
1117 eap_tls_session->state = EAP_TLS_HANDLED;
1118 }
1119 goto done;
1120
1121 /*
1122 * Bad things happened and we're unable to continue.
1123 */
1124 case EAP_TLS_INVALID:
1125 case EAP_TLS_FAIL:
1126 /*
1127 * Established means that we're done the initial handshake.
1128 *
1129 * For TTLS and PEAP that means begin phase2
1130 */
1132 default:
1133 goto done;
1134 }
1135
1136 done:
1137
1139}
1140
1141/** Create a new fr_tls_session_t associated with an #eap_session_t
1142 *
1143 * Creates a new server fr_tls_session_t and associates it with an #eap_session_t
1144 * adding EAP specific opaque data to the SSL session created during fr_tls_session_t
1145 * initialisation.
1146 *
1147 * @param[in] request The current subrequest.
1148 * @param[in] eap_session to use as a context for the eap_tls_session_t
1149 * @param[in] ssl_ctx to use to configure the fr_tls_session_t.
1150 * @param[in] client_cert Whether we require the peer to prevent a certificate.
1151 * @return
1152 * - A new eap_tls_session on success.
1153 * - NULL on error.
1154 */
1156 SSL_CTX *ssl_ctx, bool client_cert)
1157{
1158 eap_tls_session_t *eap_tls_session;
1159 fr_tls_session_t *tls_session;
1160 fr_tls_conf_t *conf = fr_tls_ctx_conf(ssl_ctx);
1161 fr_pair_t *vp;
1162 fr_pair_t *tls_max, *tls_min;
1163
1164 fr_assert(request->parent); /* must be a subrequest */
1165
1166 /*
1167 * This EAP session is associated with a TLS session
1168 */
1169 eap_session->tls = true;
1170 MEM(eap_tls_session = talloc_zero(eap_session, eap_tls_session_t));
1171
1172 /*
1173 * Initial state.
1174 */
1175 eap_tls_session->state = EAP_TLS_START_SEND;
1176
1177 /*
1178 * As per the RFC...
1179 *
1180 * Broken protocols like PEAPv0 need this set to false.
1181 */
1182 eap_tls_session->include_length = true;
1183
1184 /*
1185 * We use default fragment size, unless the Framed-MTU
1186 * tells us it's too big. Note that we do NOT account
1187 * for the EAP-TLS headers if conf->fragment_size is
1188 * large, because that config item looks to be confusing.
1189 *
1190 * i.e. it should REALLY be called MTU, and the code here
1191 * should figure out what that means for TLS fragment size.
1192 * asking the administrator to know the internal details
1193 * of EAP-TLS in order to calculate fragment sizes is
1194 * just too much.
1195 */
1196 vp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_framed_mtu);
1197
1198 /*
1199 * Every new session is started only from EAP-TLS-START.
1200 * Before Sending our initial EAP-TLS start open a new
1201 * SSL session.
1202 * Create all the required data structures & store them
1203 * in the SSL session's opaque data so that we can use
1204 * these data structures when we get the response.
1205 */
1206 eap_tls_session->tls_session = tls_session = fr_tls_session_alloc_server(eap_tls_session, ssl_ctx,
1207 request, vp ? vp->vp_uint32 : 0, client_cert);
1208 if (unlikely(!tls_session)) return NULL;
1209
1210 /*
1211 * Add the EAP-Identity value to the TLS session so
1212 * it's available in all the TLS callbacks.
1213 */
1214 {
1215 fr_pair_t *identity;
1216
1217 MEM(identity = fr_pair_afrom_da(tls_session, attr_eap_identity));
1218 fr_pair_value_bstrdup_buffer(identity, eap_session->identity, true);
1219 fr_tls_session_extra_pair_add_shallow(tls_session, identity);
1220 }
1221
1222 /*
1223 * Add the EAP-Type we're running to the subrequest.
1224 */
1225 {
1226 fr_pair_t *type_vp;
1227
1228 MEM(type_vp = fr_pair_afrom_da(tls_session, attr_eap_type));
1229 type_vp->vp_uint32 = eap_session->type;
1230 fr_tls_session_extra_pair_add_shallow(tls_session, type_vp);
1231 }
1232
1233 /*
1234 * Associate various bits of opaque data with the session.
1235 */
1236 SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_EAP_SESSION, (void *)eap_session);
1237 SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_TLS_SESSION, (void *)tls_session);
1238 SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_CONF, (void *)conf);
1239 SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_IDENTITY, (void *)&(eap_session->identity));
1240
1241 tls_max = fr_pair_find_by_da(&request->control_pairs, NULL, attr_tls_max_version);
1242 tls_min = fr_pair_find_by_da(&request->control_pairs, NULL, attr_tls_min_version);
1243 if (tls_max && tls_min && (tls_min->vp_float32 > tls_max->vp_float32)) {
1244 RERROR("Can't set TLS min version greater than max version");
1245 goto skip_tls_version;
1246 }
1247
1248#define SET_TLS_VERSION(_type) \
1249 if (tls_ ## _type) { \
1250 int tls_version = 0; \
1251 if (tls_ ## _type->vp_float32 >= (float) 1.3) { \
1252 tls_version = TLS1_3_VERSION; \
1253 } else if (tls_ ## _type->vp_float32 >= (float) 1.2) { \
1254 tls_version = TLS1_2_VERSION; \
1255 } else if (tls_ ## _type->vp_float32 >= (float) 1.1) { \
1256 tls_version = TLS1_1_VERSION; \
1257 } \
1258 if (tls_version) { \
1259 if (SSL_set_ ## _type ## _proto_version(tls_session->ssl, tls_version) != 1) {\
1260 RERROR("Failed to set %pP", tls_ ## _type); \
1261 } else { \
1262 RDEBUG2("Setting TLS " #_type " version to %0.1f", tls_ ## _type->vp_float32); \
1263 } \
1264 } else { \
1265 RWARN("Invalid value %pP", tls_ ## _type); \
1266 } \
1267 }
1268
1269 SET_TLS_VERSION(max)
1271skip_tls_version:
1272
1273 return eap_tls_session;
1274}
1275
1276/** Parse TLS configuration
1277 *
1278 * If the option given by 'attr' is set, we find the config section of that name and use
1279 * that for the TLS configuration. If not, we fall back to compatibility mode and read
1280 * the TLS options from the 'tls' section.
1281 *
1282 * @param cs to derive the configuration from.
1283 * @return
1284 * - NULL on error.
1285 * - A new fr_tls_conf_t on success.
1286 */
1288{
1289 char const *tls_conf_name;
1290 CONF_PAIR *cp;
1292 CONF_SECTION *tls_cs;
1293 fr_tls_conf_t *tls_conf;
1294
1296
1297 /*
1298 * tls = tls-common is a reference to the "tls-common" section in the parent EAP module configuration.
1299 */
1300 cp = cf_pair_find(cs, "tls");
1301 if (cp) {
1302 tls_conf_name = cf_pair_value(cp);
1303
1304 tls_cs = cf_section_find(parent, TLS_CONFIG_SECTION, tls_conf_name);
1305 if (!tls_cs) {
1306 CONF_ITEM *ci;
1307
1308 ci = cf_reference_item(cf_root(parent), parent, tls_conf_name);
1309 if (!ci) {
1310 cf_log_perr(cp, "Cannot find tls configuration section from reference '%s'",
1311 tls_conf_name);
1312 return NULL;
1313 }
1314
1315 if (!cf_item_is_section(ci)) {
1316 cf_log_err(cp, "Invalid tls configuration reference '%s' - the result is not a configuration section",
1317 tls_conf_name);
1318 return NULL;
1319 }
1320
1321 tls_cs = cf_item_to_section(ci);
1322 }
1323 } else {
1324 cf_log_err(cs, "Cannot do TLS-based EAP method %s - missing 'tls = ...' configuration item",
1325 cf_section_name1(cs));
1326 return NULL;
1327 }
1328
1329 tls_conf = fr_tls_conf_parse_server(tls_cs);
1330 if (!tls_conf) return NULL;
1331
1332 /*
1333 * The EAP RFC's say 1020, but we're less picky.
1334 */
1335 FR_INTEGER_BOUND_CHECK("fragment_size", tls_conf->fragment_size, >=, 100);
1336
1337 /*
1338 * The maximum size for a RADIUS packet is 4096, but we're
1339 * not just a RADIUS server.
1340 *
1341 * Maximum size for a TLS record is 16K, so little point in
1342 * setting it higher than that.
1343 */
1344 FR_INTEGER_BOUND_CHECK("fragment_size", tls_conf->fragment_size, <=, FR_TLS_MAX_RECORD_SIZE);
1345
1346 /*
1347 * Account for the EAP header (4), and the EAP-TLS header
1348 * (6), as per Section 4.2 of RFC 2716. What's left is
1349 * the maximum amount of data we read from a TLS buffer.
1350 */
1351 tls_conf->fragment_size -= 10;
1352
1353 return tls_conf;
1354}
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 USES_APPLE_DEPRECATED_API
Definition build.h:493
#define RCSID(id)
Definition build.h:506
#define L(_str)
Helper for initialising arrays of string literals.
Definition build.h:228
#define STRINGIFY(x)
Definition build.h:216
#define unlikely(_x)
Definition build.h:402
#define NUM_ELEMENTS(_t)
Definition build.h:358
CONF_ITEM * cf_reference_item(CONF_SECTION const *parent_cs, CONF_SECTION const *outer_cs, char const *ptr)
Definition cf_file.c:3889
#define FR_INTEGER_BOUND_CHECK(_name, _var, _op, _bound)
Definition cf_parse.h:517
Common header for all CONF_* types.
Definition cf_priv.h:49
Configuration AVP similar to a fr_pair_t.
Definition cf_priv.h:72
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:101
char const * cf_section_name1(CONF_SECTION const *cs)
Return the first identifier of a CONF_SECTION.
Definition cf_util.c:1173
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
Definition cf_util.c:1029
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
Definition cf_util.c:685
CONF_PAIR * cf_pair_find(CONF_SECTION const *cs, char const *attr)
Search for a CONF_PAIR with a specific name.
Definition cf_util.c:1422
bool cf_item_is_section(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_SECTION.
Definition cf_util.c:619
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition cf_util.c:1581
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:285
#define cf_root(_cf)
Definition cf_util.h:95
#define cf_parent(_cf)
Definition cf_util.h:98
#define cf_log_perr(_cf, _fmt,...)
Definition cf_util.h:292
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 MEM(x)
Definition debug.h:46
#define TLS_CONFIG_SECTION
Definition base.h:41
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:85
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:132
@ FR_EAP_CODE_FAILURE
Definition types.h:40
@ FR_EAP_CODE_REQUEST
Definition types.h:37
@ FR_EAP_CODE_SUCCESS
Definition types.h:39
size_t length
Definition types.h:111
#define EAP_HEADER_LEN
Definition types.h:34
uint8_t * data
Definition types.h:112
@ FR_EAP_METHOD_TLS
Definition types.h:58
#define unlang_function_push(_request, _func, _repeat, _signal, _sigmask, _top_frame, _uctx)
Push a generic function onto the unlang stack.
Definition function.h:179
#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:103
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:104
HIDDEN fr_dict_attr_t const * attr_eap_type
Definition base.c:90
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
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:72
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:455
#define RDEBUG3(fmt,...)
Definition log.h:355
#define RERROR(fmt,...)
Definition log.h:310
#define RINDENT()
Indent R* messages by one level.
Definition log.h:442
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:707
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
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:3037
VQP attributes.
#define fr_assert(_expr)
Definition rad_assert.h:37
#define REDEBUG(fmt,...)
#define RDEBUG2(fmt,...)
#define RDEBUG(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_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:772
An element in an arbitrarily ordered array of name to num mappings.
Definition table.h:57
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
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:559
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
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:936
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:463
int eap_tls_compose(request_t *request, eap_session_t *eap_session, eap_tls_status_t status, uint8_t flags, fr_tls_record_t *record, size_t record_len, size_t frag_len)
Convert the EAP-TLS reply packet into an EAP packet.
Definition tls.c:113
size_t eap_tls_status_table_len
Definition tls.c:93
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
#define SET_TLS_VERSION(_type)
USES_APPLE_DEPRECATED_API fr_table_num_ordered_t const eap_tls_status_table[]
Definition tls.c:79
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:483
fr_tls_conf_t * eap_tls_conf_parse(CONF_SECTION *cs)
Parse TLS configuration.
Definition tls.c:1287
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:819
unlang_action_t eap_tls_process(request_t *request, eap_session_t *eap_session)
Process an EAP TLS request.
Definition tls.c:981
Generic EAP over TLS API.
uint8_t data[]
Definition tls.h:112
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
bool phase2
Whether we're in phase 2.
Definition tls.h:132
#define TLS_RESERVED1(x)
Definition tls.h:76
eap_tls_status_t
Definition tls.h:86
@ EAP_TLS_RECORD_RECV_FIRST
Received first fragment of a record.
Definition tls.h:105
@ 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_MORE
Received additional fragment of a record.
Definition tls.h:106
@ EAP_TLS_ACK_SEND
Acknowledge receipt of a record or record fragment.
Definition tls.h:98
@ EAP_TLS_RECORD_SEND
We're sending a record.
Definition tls.h:97
@ EAP_TLS_RECORD_RECV_COMPLETE
Received final fragment of a record.
Definition tls.h:107
@ EAP_TLS_START_SEND
We're starting a new TLS session.
Definition tls.h:96
@ EAP_TLS_FAIL
Fail, send fail.
Definition tls.h:89
@ EAP_TLS_ESTABLISHED
Session established, send success (or start phase2).
Definition tls.h:88
#define TLS_MORE_FRAGMENTS(x)
Definition tls.h:79
fr_tls_session_t * tls_session
TLS session used to authenticate peer or tunnel sensitive data.
Definition tls.h:125
bool record_in_started
Whether a record transfer from the peer is currently in progress.
Definition tls.h:143
size_t record_out_total_len
Actual/Total TLS message length we're sending.
Definition tls.h:141
#define SET_START(x)
Definition tls.h:82
#define TLS_RESERVED3(x)
Definition tls.h:74
#define SET_LENGTH_INCLUDED(x)
Definition tls.h:84
uint8_t flags
Definition tls.h:111
#define TLS_START(x)
Definition tls.h:78
size_t record_in_total_len
How long the peer indicated the complete tls record would be.
Definition tls.h:145
#define TLS_RESERVED0(x)
Definition tls.h:77
bool record_out_started
for methods with inner auth, if the inner auth succeeded.
Definition tls.h:139
size_t record_in_recvd_len
How much of the record we've received so far.
Definition tls.h:147
#define TLS_LENGTH_INCLUDED(x)
Definition tls.h:80
#define TLS_RESERVED2(x)
Definition tls.h:75
#define TLS_RESERVED4(x)
Definition tls.h:73
#define TLS_HEADER_LENGTH_FIELD_LEN
Definition tls.h:56
#define SET_MORE_FRAGMENTS(x)
Definition tls.h:83
bool authentication_success
Definition tls.h:137
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
static fr_slen_t parent
Definition pair.h:858
static fr_slen_t data
Definition value.h:1340