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