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: 6fbadbe0e098c616fadeb0ddb81f145931e69b01 $
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: 6fbadbe0e098c616fadeb0ddb81f145931e69b01 $")
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) &&
499 (tls_session->info.origin == TLS_INFO_ORIGIN_RECORD_RECEIVED)) {
500 REDEBUG("Unexpected ACK received: We sent no previous messages");
501 return EAP_TLS_INVALID;
502 }
503
504 switch (tls_session->info.content_type) {
505 case SSL3_RT_ALERT:
506 RDEBUG2("Peer ACKed our alert");
507 return EAP_TLS_FAIL;
508
509 case SSL3_RT_HANDSHAKE:
510 if (SSL_is_init_finished(tls_session->ssl) && (tls_session->dirty_out.used == 0)) {
511 RDEBUG2("Peer ACKed our handshake fragment. handshake is finished");
512
513 /*
514 * From now on all the content is
515 * application data set it here as nobody else
516 * sets it.
517 */
518 tls_session->info.content_type = SSL3_RT_APPLICATION_DATA;
519 return EAP_TLS_ESTABLISHED;
520 } /* else more data to send */
521
522 RDEBUG2("Peer ACKed our handshake fragment");
523 /* Fragmentation handler, send next fragment */
524 return EAP_TLS_RECORD_SEND;
525
526 case SSL3_RT_APPLICATION_DATA:
527 RDEBUG2("Peer ACKed our application data fragment");
528 return EAP_TLS_RECORD_SEND;
529
530 /*
531 * For the rest of the conditions, switch over
532 * to the default section below.
533 */
534 default:
535 /*
536 * If the last message was from us, then the session is established
537 */
538 if (tls_session->info.origin == TLS_INFO_ORIGIN_RECORD_SENT) return EAP_TLS_ESTABLISHED;
539 REDEBUG("Invalid ACK received: %d", tls_session->info.content_type);
540 return EAP_TLS_INVALID;
541 }
542}
543
544/** Check that this EAP-TLS packet is correct and the progression of EAP-TLS packets is sane
545 *
546 * @note In the received packet, No data will be present in case of ACK or NAK
547 * in this case the packet->data pointer will be NULL.
548 *
549 * @param[in] request the current subrequest.
550 * @param[in] eap_session the current EAP session state.
551 * @return
552 * - EAP_TLS_INVALID if the TLS record or progression is invalid.
553 * - EAP_TLS_FAIL handshake failed.
554 * - EAP_TLS_RECORD_RECV_FIRST this is the start of a new sequence of record fragments.
555 * - EAP_TLS_RECORD_RECV_MORE this is a continuation of a sequence of fragments.
556 * - EAP_TLS_RECORD_RECV_COMPLETE we received a completed record.
557 * - EAP_TLS_RECORD_SEND send more data to peer.
558 * - EAP_TLS_ESTABLISHED handshake is complete, TLS session has been established.
559 */
561{
562 eap_round_t *this_round = eap_session->this_round;
563 eap_round_t *prev_round = eap_session->prev_round;
564 eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
565
566 eap_tls_data_t *eap_tls_data;
567 size_t frag_len, header_len;
568
569 fr_assert(request->parent); /* must be a subrequest */
570
571 /*
572 * All EAP-TLS packets must contain type and flags fields.
573 */
574 if (this_round->response->length < (EAP_HEADER_LEN + 2)) {
575 REDEBUG("Invalid EAP-TLS packet: Expected at least %zu bytes got %zu bytes",
576 (size_t)EAP_HEADER_LEN + 2, this_round->response->length);
577 return EAP_TLS_INVALID;
578 }
579
580 /*
581 * We don't check ANY of the input parameters. It's all
582 * code which works together, so if something is wrong,
583 * we SHOULD core dump.
584 *
585 * e.g. if this_round is NULL, or if this_round->response is
586 * NULL, or if it's NOT an EAP-Response, or if the packet
587 * is too short. See eap_validate()., in ../../eap.c
588 */
589 eap_tls_data = (eap_tls_data_t *)this_round->response->type.data;
590 if (!eap_tls_data) {
591 REDEBUG("Invalid EAP-TLS packet; no data");
592 return EAP_TLS_INVALID;
593 }
594
595 /*
596 * First output the flags (for debugging)
597 */
598 RDEBUG3("Peer sent flags %c%c%c%c%c%c%c%c",
599 TLS_START(eap_tls_data->flags) ? 'S' : '-',
600 TLS_MORE_FRAGMENTS(eap_tls_data->flags) ? 'M' : '-',
601 TLS_LENGTH_INCLUDED(eap_tls_data->flags) ? 'L' : '-',
602 TLS_RESERVED0(eap_tls_data->flags) ? 'R' : '-',
603 TLS_RESERVED1(eap_tls_data->flags) ? 'R' : '-',
604 TLS_RESERVED2(eap_tls_data->flags) ? 'R' : '-',
605 TLS_RESERVED3(eap_tls_data->flags) ? 'R' : '-',
606 TLS_RESERVED4(eap_tls_data->flags) ? 'R' : '-');
607
608 /*
609 * This length includes the type and flags field and
610 * the message length field if the flags indicate it's present.
611 */
612 header_len = EAP_HEADER_LEN + (TLS_LENGTH_INCLUDED(eap_tls_data->flags) ? 6 : 2);
613 if (this_round->response->length < header_len) {
614 REDEBUG("Invalid EAP-TLS packet: Expected at least %zu bytes got %zu bytes",
615 header_len, this_round->response->length);
616 return EAP_TLS_INVALID;
617 }
618
619 /*
620 * check for ACK
621 *
622 * If there's no TLS data, or there's 1 byte of TLS data,
623 * with the flags set to zero, then it's an ACK.
624 *
625 * Find if this is a reply to the previous request sent
626 */
627 if ((this_round->response->length == EAP_HEADER_LEN + 2) &&
628 ((eap_tls_data->flags & 0xc0) == 0x00)) {
629 if (!prev_round || (prev_round->request->id != this_round->response->id)) {
630 REDEBUG("Received Invalid TLS ACK");
631 return EAP_TLS_INVALID;
632 }
633 return eap_tls_session_status(request, eap_session);
634 }
635
636 /*
637 * We send TLS_START, but do not receive it.
638 */
639 if (TLS_START(eap_tls_data->flags)) {
640 REDEBUG("Peer sent EAP-TLS Start message (only the server is allowed to do this)");
641 return EAP_TLS_INVALID;
642 }
643
644 /*
645 * Calculate this fragment's length
646 */
647 frag_len = this_round->response->length - header_len;
648
649 /*
650 * This fragment has no data, but the header says that there is more data!
651 */
652 if (!frag_len && TLS_MORE_FRAGMENTS(eap_tls_data->flags)) {
653 REDEBUG("Peer sent EAP-TLS with zero-length fragment and 'more' bit set - if there is no data, there should not be more!");
654 return EAP_TLS_INVALID;
655 }
656
657 /*
658 * The L bit (length included) is set to indicate the
659 * presence of the four octet TLS Message Length field,
660 * and MUST be set for the first fragment of a fragmented
661 * TLS message or set of messages.
662 *
663 * The M bit (more fragments) is set on all but the last
664 * fragment.
665 *
666 * The S bit (EAP-TLS start) is set in an EAP-TLS Start
667 * message. This differentiates the EAP-TLS Start message
668 * from a fragment acknowledgement.
669 */
670 if (TLS_LENGTH_INCLUDED(eap_tls_data->flags)) {
671 size_t total_len;
672
673 if (eap_tls_data->data[0] || eap_tls_data->data[1]) {
674 REDEBUG("TLS record length is > 65536");
675 return EAP_TLS_INVALID;
676 }
677
678 total_len = eap_tls_data->data[2] * 256 | eap_tls_data->data[3];
679 if (frag_len > total_len) {
680 REDEBUG("TLS fragment length (%zu bytes) greater than TLS record length (%zu bytes)",
681 frag_len, total_len);
682 return EAP_TLS_INVALID;
683 }
684
685 if (total_len > FR_TLS_MAX_RECORD_SIZE) {
686 REDEBUG("Reassembled TLS record will be %zu bytes, "
687 "greater than our maximum record size (" STRINGIFY(FR_TLS_MAX_RECORD_SIZE) " bytes)",
688 total_len);
689 return EAP_TLS_INVALID;
690 }
691
692 /*
693 * wpa_supplicant's implementation of PEAPv0, and likely other
694 * implementations of PEAPv0 will always include a Length flag
695 * for every record fragment if performing mutual TLS auth.
696 *
697 * If the eap_session says this is not the first fragment, then
698 * don't count this as a new record, and continue as if we
699 * hadn't seen the length flag.
700 */
701 if (eap_tls_session->record_in_started) goto ignore_length;
702
703 /*
704 * This is the first fragment of a fragmented TLS record transfer.
705 */
706 RDEBUG2("Peer indicated complete TLS record size will be %zu bytes", total_len);
707 if (TLS_MORE_FRAGMENTS(eap_tls_data->flags)) {
708 /*
709 * The peer is free to send fragments of wildly varying
710 * lengths, but the vast majority won't.
711 *
712 * In this calculation we take into account the fact that the future
713 * fragments are likely to be 4 bytes larger than the initial one
714 * as they won't contain the length field.
715 */
716 if (frag_len + 4) { /* check for wrap, else clang scan gets excited */
717 RDEBUG2("Expecting %i TLS record fragments",
718 (int)((((total_len - frag_len) + ((frag_len + 4) - 1)) / (frag_len + 4)) + 1));
719 }
720
721 /*
722 * First fragment. record_in_started bool was false,
723 * and we received a length included + more fragments packet.
724 */
725 RDEBUG2("Got first TLS record fragment (%zu bytes). Peer indicated more fragments "
726 "to follow", frag_len);
727 eap_tls_session->record_in_total_len = total_len;
728 eap_tls_session->record_in_recvd_len = frag_len;
729 eap_tls_session->record_in_started = true;
730
732 }
733
734 /*
735 * Else this is the complete TLS record.
736 */
737 if (total_len != frag_len) {
738 REDEBUG("Peer indicated no more fragments, but TLS record length (%zu bytes) "
739 "does not match EAP-TLS data length (%zu bytes)", total_len, frag_len);
740 return EAP_TLS_INVALID;
741 }
742
743 /*
744 * RFC5216 doesn't specify explicitly whether a non-fragmented
745 * packet should include the length or not.
746 *
747 * We support both options for maximum compatibility.
748 */
749 RDEBUG2("Got complete TLS record, with length field (%zu bytes)", frag_len);
751 }
752
753ignore_length:
754 if (TLS_MORE_FRAGMENTS(eap_tls_data->flags)) {
755 /*
756 * If this is not an ongoing transfer, and we have the M flag
757 * then this record transfer is invalid.
758 */
759 if (!eap_tls_session->record_in_started) {
760 REDEBUG("TLS More (M) flag set, but no fragmented record transfer was in progress");
761 return EAP_TLS_INVALID;
762 }
763
764 /*
765 * If this is an ongoing transfer, and we have the M flag,
766 * then this is just an additional fragment.
767 */
768 RDEBUG2("Got additional TLS record fragment (%zu bytes). Peer indicated more fragments to follow",
769 frag_len);
770 eap_tls_session->record_in_recvd_len += frag_len;
771 if (eap_tls_session->record_in_recvd_len > eap_tls_session->record_in_total_len) {
772 REDEBUG("Total received TLS record fragments (%zu bytes), exceeds "
773 "indicated TLS record length (%zu bytes)",
774 eap_tls_session->record_in_recvd_len, eap_tls_session->record_in_total_len);
775 return EAP_TLS_INVALID;
776 }
778 }
779
780 /*
781 * No L flag and no M flag. This is either the final fragment,
782 * or a new transfer that was not started with a L flag, which
783 * RFC5216 hints, may be acceptable.
784 *
785 * If it's an in-progress record transfer, check we now have
786 * the complete record.
787 */
788 if (eap_tls_session->record_in_started) {
789 eap_tls_session->record_in_started = false;
790
791 RDEBUG2("Got final TLS record fragment (%zu bytes)", frag_len);
792 eap_tls_session->record_in_recvd_len += frag_len;
793 if (eap_tls_session->record_in_recvd_len != eap_tls_session->record_in_total_len) {
794 REDEBUG("Total received TLS record fragments (%zu bytes), does not equal indicated "
795 "TLS record length (%zu bytes)",
796 eap_tls_session->record_in_recvd_len, eap_tls_session->record_in_total_len);
797 return EAP_TLS_INVALID;
798 }
800 }
801
802 /*
803 * None of the flags are set, it wasn't an in progress transfer,
804 * but it's still a valid EAP-TLS packet.
805 */
806 RDEBUG2("Got complete TLS record (%zu bytes)", frag_len);
807
809}
810
811/** Process the result from the last TLS handshake round
812 *
813 * @return
814 * - eap_tls_session->state == EAP_TLS_FAIL if the message is invalid.
815 * - eap_tls_session->state == EAP_TLS_HANDLED if we need to send an
816 * additional request to the peer.
817 * - eap_tls_session->state == EAP_TLS_ESTABLISHED if the handshake
818 * completed successfully, and there's no more data to send.
819 */
821{
822 eap_session_t *eap_session = talloc_get_type_abort(uctx, eap_session_t);
823 eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
824 fr_tls_session_t *tls_session = talloc_get_type_abort(eap_tls_session->tls_session, fr_tls_session_t);
826
827 switch (tls_session->result) {
828 case FR_TLS_RESULT_IN_PROGRESS:
829 default:
830 fr_assert(0); /* Shouldn't have been called */
831 goto fail;
832
833 case FR_TLS_RESULT_ERROR:
834 REDEBUG("TLS receive handshake failed during operation");
835 goto fail;
836
837 case FR_TLS_RESULT_SUCCESS:
838 break;
839 }
840
841#ifdef TLS1_3_VERSION
842 /*
843 * https://tools.ietf.org/html/draft-ietf-emu-eap-tls13#section-2.5
844 *
845 * We need to signal the other end that TLS negotiation
846 * is done. We can't send a zero-length application data
847 * message, so we send application data which is one byte
848 * of zero.
849 *
850 * Note this is only done for when there is no application
851 * data to be sent. So this is done always for EAP-TLS but
852 * notibly not for PEAP even on resumption.
853 *
854 * We only want to send this application data IF:
855 *
856 * * EAP-TLS / TTLS / PEAP - session was resumed
857 * * EAP-TLS
858 * * SSL init is finished (presumed to be checked elsewhere)
859 * * we saw the client cert
860 * * OR we're using unauthenticated EAP-TLS where
861 * the administrator has decided to not ask for
862 * the client cert
863 */
864 if ((tls_session->info.version == TLS1_3_VERSION) &&
865 (tls_session->client_cert_ok || eap_tls_session->authentication_success || SSL_session_reused(tls_session->ssl))) {
866 if ((eap_session->type == FR_EAP_METHOD_TLS) || SSL_session_reused(tls_session->ssl)) {
867 eap_tls_session->authentication_success = true;
868
869 RDEBUG("(TLS) EAP Sending final Commitment Message.");
870 tls_session->record_from_buff(&tls_session->clean_in, "\0", 1);
871 } else {
872
873 /*
874 * Returns UNLANG_ACTION_PUSHED_CHILD unless something has failed
875 */
876 ret = fr_tls_session_async_handshake_push(request, tls_session);
877 if (ret != UNLANG_ACTION_FAIL) return ret;
878
879 REDEBUG("TLS receive handshake failed during operation");
880 goto fail;
881 }
882 }
883#endif
884
885 /*
886 * FIXME: return success/fail.
887 *
888 * TLS proper can decide what to do, then.
889 */
890 if (tls_session->dirty_out.used > 0) {
891 if (eap_tls_request(request, eap_session) < 0) {
892 REDEBUG("TLS failed composing a response");
893 goto fail;
894 }
895 eap_tls_session->state = EAP_TLS_HANDLED;
897 }
898
899 /*
900 * If there is no data to send i.e dirty_out.used <=0 and
901 * if the SSL handshake is finished, then return
902 * EAP_TLS_ESTABLISHED.
903 *
904 * For EAP-TLS this translates to an EAP-Success, for others
905 * this begins phase2.
906 */
907 if (eap_tls_session->phase2 || SSL_is_init_finished(tls_session->ssl)) {
908 eap_tls_session->phase2 = true;
909
910 /*
911 * Init is finished. The rest is
912 * application data.
913 */
914 tls_session->info.content_type = SSL3_RT_APPLICATION_DATA;
915 eap_tls_session->state = EAP_TLS_ESTABLISHED;
917 }
918
919 /*
920 * Who knows what happened...
921 */
922 REDEBUG("TLS failed during operation");
923fail:
924 fr_tls_cache_deny(request, tls_session);
925 eap_tls_session->state = EAP_TLS_FAIL;
926
928}
929
930/** Push functions to continue the handshake asynchronously
931 *
932 * @param[in] request the current subrequest.
933 * @param[in] eap_session to continue.
934 * @return
935 * - UNLANG_ACTION_PUSHED_CHILD
936 */
937static inline CC_HINT(always_inline) unlang_action_t eap_tls_handshake_push(request_t *request, eap_session_t *eap_session)
938{
939 eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
940 fr_tls_session_t *tls_session = talloc_get_type_abort(eap_tls_session->tls_session, fr_tls_session_t);
941
942 /*
943 * Will run after the handshake round completes
944 */
945 if (unlang_function_push(request,
946 NULL,
948 NULL,
950 eap_session) < 0) return UNLANG_ACTION_FAIL;
951
952 if (fr_tls_session_async_handshake_push(request, tls_session) < 0) return UNLANG_ACTION_FAIL;
953
955}
956
957/** Process an EAP TLS request
958 *
959 * Here we implement a basic state machine. The state machine is implicit and
960 * is driven by the state of the TLS session and the flags sent.
961 * INCOMING DATA:
962 * 1. EAP-TLS should get the complete TLS data from the peer.
963 * 2. Store that data in a data structure with any other required info
964 * 3. Hand this data structure to the TLS module.
965 * 4. TLS module will perform its operations on the data and hands back to EAP-TLS
966 * OUTGOING DATA:
967 * 1. EAP-TLS if necessary will fragment it and send it to the destination.
968 *
969 * During EAP-TLS initialization, TLS Context object will be initialised and stored.
970 * For every new authentication request, TLS will open a new session object and that
971 * session object SHOULD be maintained even after the session is completed, for session
972 * resumption.
973 *
974 * Note that we never return FAIL to the interpreter. Instead, we
975 * send the EAP failure back to the supplicant.
976 *
977 * @param request the request
978 * @param eap_session to continue.
979 * @return
980 * - UNLANG_ACTION_CALCULATE_RESULT
981 */
983{
984 eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
985 fr_tls_session_t *tls_session = eap_tls_session->tls_session;
986
987 eap_round_t *this_round = eap_session->this_round;
988
989 eap_tls_data_t *eap_tls_data;
990 uint8_t *data;
991 size_t data_len;
992
993 fr_assert(request->parent); /* must be a subrequest */
994
995 RDEBUG2("Continuing EAP-TLS");
996
997 /*
998 * Call eap_tls_verify to sanity check the incoming EAP data.
999 */
1000 eap_tls_session->state = eap_tls_verify(request, eap_session);
1001 switch (eap_tls_session->state) {
1002 case EAP_TLS_INVALID:
1003 case EAP_TLS_FAIL:
1004 REDEBUG("[eap-tls verify] = %s", fr_table_str_by_value(eap_tls_status_table, eap_tls_session->state, "<INVALID>"));
1005 break;
1006
1007 default:
1008 RDEBUG2("[eap-tls verify] = %s", fr_table_str_by_value(eap_tls_status_table, eap_tls_session->state, "<INVALID>"));
1009 break;
1010 }
1011
1012 /*
1013 * Status in this here means 'state'. Our state is determined passively
1014 * for EAP-TLS, based on what state OpenSSL reported the TLS session
1015 * to be in, and what flags were last received from the peer.
1016 */
1017 switch (eap_tls_session->state) {
1018 /*
1019 * We've received a complete TLS record, this is the same as receiving a
1020 * fragment, except we also process the complete record.
1021 */
1023 /*
1024 * We've received a fragment of a TLS record
1025 *
1026 * Determine where the TLS record starts.
1027 *
1028 * If the length included flag is set, we need to skip over the 4 byte
1029 * message length field.
1030 *
1031 * Next - Copy the fragment data into OpenSSL's dirty in buffer so that it
1032 * can process it in a later call.
1033 */
1036 eap_tls_data = (eap_tls_data_t *)this_round->response->type.data;
1037 if (TLS_LENGTH_INCLUDED(eap_tls_data->flags)) {
1038 data = (this_round->response->type.data + 5); /* flags + TLS-Length */
1039 data_len = this_round->response->type.length - 5; /* flags + TLS-Length */
1040 } else {
1041 data = this_round->response->type.data + 1; /* flags */
1042 data_len = this_round->response->type.length - 1; /* flags */
1043 }
1044
1045 /*
1046 * Update the dirty_in buffer (data for reading by OpenSSL)
1047 *
1048 * This buffer will contain partial data when M bit is set, and should
1049 * should only be reinitialized when M bit is not set.
1050 */
1051 if ((tls_session->record_from_buff)(&tls_session->dirty_in, data, data_len) != data_len) {
1052 REDEBUG("Exceeded maximum record size");
1053 eap_tls_session->state = EAP_TLS_FAIL;
1054 goto done;
1055 }
1056
1057 /*
1058 * ACK fragments until we get a complete TLS record.
1059 */
1060 if (eap_tls_session->state != EAP_TLS_RECORD_RECV_COMPLETE) {
1061 if (eap_tls_ack(request, eap_session) < 0) {
1062 eap_tls_session->state = EAP_TLS_FAIL;
1063 } else {
1064 eap_tls_session->state = EAP_TLS_HANDLED;
1065 }
1066 goto done;
1067 }
1068
1069 /*
1070 * We have a complete record. If the handshake is finished
1071 * process it as application data, otherwise continue
1072 * the handshake.
1073 */
1074 if (eap_tls_session->phase2 || SSL_is_init_finished(tls_session->ssl)) {
1075 int ret;
1076
1077 eap_tls_session->phase2 = true;
1078
1079 ret = fr_tls_session_recv(request, tls_session);
1080 switch (ret) {
1081 case 0:
1082 eap_tls_session->state = EAP_TLS_RECORD_RECV_COMPLETE;
1083 break;
1084
1085 case 1:
1086 eap_tls_session->state = EAP_TLS_RECORD_RECV_MORE;
1087 break;
1088
1089 default:
1090 eap_tls_session->state = EAP_TLS_FAIL;
1091 break;
1092 }
1093 } else {
1094 /*
1095 * Asynchronously process more handshake data
1096 */
1097 return eap_tls_handshake_push(request, eap_session);
1098 }
1099 break;
1100 /*
1101 * We have fragments or records to send to the peer
1102 */
1104 /*
1105 * Return a "yes we're done" if there's no more data to send,
1106 * and we've just managed to finish the SSL session initialization.
1107 */
1108 if (!eap_tls_session->phase2 && (tls_session->dirty_out.used == 0) &&
1109 SSL_is_init_finished(tls_session->ssl)) {
1110 eap_tls_session->phase2 = true;
1111 eap_tls_session->state = EAP_TLS_ESTABLISHED;
1112 goto done;
1113 }
1114
1115 if (eap_tls_request(request, eap_session) < 0) {
1116 eap_tls_session->state = EAP_TLS_FAIL;
1117 } else {
1118 eap_tls_session->state = EAP_TLS_HANDLED;
1119 }
1120 goto done;
1121
1122 /*
1123 * Bad things happened and we're unable to continue.
1124 */
1125 case EAP_TLS_INVALID:
1126 case EAP_TLS_FAIL:
1127 /*
1128 * Established means that we're done the initial handshake.
1129 *
1130 * For TTLS and PEAP that means begin phase2
1131 */
1133 default:
1134 goto done;
1135 }
1136
1137 done:
1138
1140}
1141
1142/** Create a new fr_tls_session_t associated with an #eap_session_t
1143 *
1144 * Creates a new server fr_tls_session_t and associates it with an #eap_session_t
1145 * adding EAP specific opaque data to the SSL session created during fr_tls_session_t
1146 * initialisation.
1147 *
1148 * @param[in] request The current subrequest.
1149 * @param[in] eap_session to use as a context for the eap_tls_session_t
1150 * @param[in] ssl_ctx to use to configure the fr_tls_session_t.
1151 * @param[in] client_cert Whether we require the peer to prevent a certificate.
1152 * @return
1153 * - A new eap_tls_session on success.
1154 * - NULL on error.
1155 */
1157 SSL_CTX *ssl_ctx, bool client_cert)
1158{
1159 eap_tls_session_t *eap_tls_session;
1160 fr_tls_session_t *tls_session;
1161 fr_tls_conf_t *conf = fr_tls_ctx_conf(ssl_ctx);
1162 fr_pair_t *vp;
1163 fr_pair_t *tls_max, *tls_min;
1164
1165 fr_assert(request->parent); /* must be a subrequest */
1166
1167 /*
1168 * This EAP session is associated with a TLS session
1169 */
1170 eap_session->tls = true;
1171 MEM(eap_tls_session = talloc_zero(eap_session, eap_tls_session_t));
1172
1173 /*
1174 * Initial state.
1175 */
1176 eap_tls_session->state = EAP_TLS_START_SEND;
1177
1178 /*
1179 * As per the RFC...
1180 *
1181 * Broken protocols like PEAPv0 need this set to false.
1182 */
1183 eap_tls_session->include_length = true;
1184
1185 /*
1186 * We use default fragment size, unless the Framed-MTU
1187 * tells us it's too big. Note that we do NOT account
1188 * for the EAP-TLS headers if conf->fragment_size is
1189 * large, because that config item looks to be confusing.
1190 *
1191 * i.e. it should REALLY be called MTU, and the code here
1192 * should figure out what that means for TLS fragment size.
1193 * asking the administrator to know the internal details
1194 * of EAP-TLS in order to calculate fragment sizes is
1195 * just too much.
1196 */
1197 vp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_framed_mtu);
1198
1199 /*
1200 * Every new session is started only from EAP-TLS-START.
1201 * Before Sending our initial EAP-TLS start open a new
1202 * SSL session.
1203 * Create all the required data structures & store them
1204 * in the SSL session's opaque data so that we can use
1205 * these data structures when we get the response.
1206 */
1207 eap_tls_session->tls_session = tls_session = fr_tls_session_alloc_server(eap_tls_session, ssl_ctx,
1208 request, vp ? vp->vp_uint32 : 0, client_cert);
1209 if (unlikely(!tls_session)) return NULL;
1210
1211 /*
1212 * Add the EAP-Identity value to the TLS session so
1213 * it's available in all the TLS callbacks.
1214 */
1215 {
1216 fr_pair_t *identity;
1217
1218 MEM(identity = fr_pair_afrom_da(tls_session, attr_eap_identity));
1219 fr_pair_value_bstrdup_buffer(identity, eap_session->identity, true);
1220 fr_tls_session_extra_pair_add_shallow(tls_session, identity);
1221 }
1222
1223 /*
1224 * Add the EAP-Type we're running to the subrequest.
1225 */
1226 {
1227 fr_pair_t *type_vp;
1228
1229 MEM(type_vp = fr_pair_afrom_da(tls_session, attr_eap_type));
1230 type_vp->vp_uint32 = eap_session->type;
1231 fr_tls_session_extra_pair_add_shallow(tls_session, type_vp);
1232 }
1233
1234 /*
1235 * Associate various bits of opaque data with the session.
1236 */
1237 SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_EAP_SESSION, (void *)eap_session);
1238 SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_TLS_SESSION, (void *)tls_session);
1239 SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_CONF, (void *)conf);
1240 SSL_set_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_IDENTITY, (void *)&(eap_session->identity));
1241
1242 tls_max = fr_pair_find_by_da(&request->control_pairs, NULL, attr_tls_max_version);
1243 tls_min = fr_pair_find_by_da(&request->control_pairs, NULL, attr_tls_min_version);
1244 if (tls_max && tls_min && (tls_min->vp_float32 > tls_max->vp_float32)) {
1245 RERROR("Can't set TLS min version greater than max version");
1246 goto skip_tls_version;
1247 }
1248
1249#define SET_TLS_VERSION(_type) \
1250 if (tls_ ## _type) { \
1251 int tls_version = 0; \
1252 if (tls_ ## _type->vp_float32 >= (float) 1.3) { \
1253 tls_version = TLS1_3_VERSION; \
1254 } else if (tls_ ## _type->vp_float32 >= (float) 1.2) { \
1255 tls_version = TLS1_2_VERSION; \
1256 } else if (tls_ ## _type->vp_float32 >= (float) 1.1) { \
1257 tls_version = TLS1_1_VERSION; \
1258 } \
1259 if (tls_version) { \
1260 if (SSL_set_ ## _type ## _proto_version(tls_session->ssl, tls_version) != 1) {\
1261 RERROR("Failed to set %pP", tls_ ## _type); \
1262 } else { \
1263 RDEBUG2("Setting TLS " #_type " version to %0.1f", tls_ ## _type->vp_float32); \
1264 } \
1265 } else { \
1266 RWARN("Invalid value %pP", tls_ ## _type); \
1267 } \
1268 }
1269
1270 SET_TLS_VERSION(max)
1272skip_tls_version:
1273
1274 return eap_tls_session;
1275}
1276
1277/** Parse TLS configuration
1278 *
1279 * If the option given by 'attr' is set, we find the config section of that name and use
1280 * that for the TLS configuration. If not, we fall back to compatibility mode and read
1281 * the TLS options from the 'tls' section.
1282 *
1283 * @param cs to derive the configuration from.
1284 * @return
1285 * - NULL on error.
1286 * - A new fr_tls_conf_t on success.
1287 */
1289{
1290 char const *tls_conf_name;
1291 CONF_PAIR *cp;
1293 CONF_SECTION *tls_cs;
1294 fr_tls_conf_t *tls_conf;
1295
1297
1298 /*
1299 * tls = tls-common is a reference to the "tls-common" section in the parent EAP module configuration.
1300 */
1301 cp = cf_pair_find(cs, "tls");
1302 if (cp) {
1303 tls_conf_name = cf_pair_value(cp);
1304
1305 tls_cs = cf_section_find(parent, TLS_CONFIG_SECTION, tls_conf_name);
1306 if (!tls_cs) {
1307 CONF_ITEM *ci;
1308
1309 ci = cf_reference_item(cf_root(parent), parent, tls_conf_name);
1310 if (!ci) {
1311 cf_log_perr(cp, "Cannot find tls configuration section from reference '%s'",
1312 tls_conf_name);
1313 return NULL;
1314 }
1315
1316 if (!cf_item_is_section(ci)) {
1317 cf_log_err(cp, "Invalid tls configuration reference '%s' - the result is not a configuration section",
1318 tls_conf_name);
1319 return NULL;
1320 }
1321
1322 tls_cs = cf_item_to_section(ci);
1323 }
1324 } else {
1325 cf_log_err(cs, "Cannot do TLS-based EAP method %s - missing 'tls = ...' configuration item",
1326 cf_section_name1(cs));
1327 return NULL;
1328 }
1329
1330 tls_conf = fr_tls_conf_parse_server(tls_cs);
1331 if (!tls_conf) return NULL;
1332
1333 /*
1334 * The EAP RFC's say 1020, but we're less picky.
1335 */
1336 FR_INTEGER_BOUND_CHECK("fragment_size", tls_conf->fragment_size, >=, 100);
1337
1338 /*
1339 * The maximum size for a RADIUS packet is 4096, but we're
1340 * not just a RADIUS server.
1341 *
1342 * Maximum size for a TLS record is 16K, so little point in
1343 * setting it higher than that.
1344 */
1345 FR_INTEGER_BOUND_CHECK("fragment_size", tls_conf->fragment_size, <=, FR_TLS_MAX_RECORD_SIZE);
1346
1347 /*
1348 * Account for the EAP header (4), and the EAP-TLS header
1349 * (6), as per Section 4.2 of RFC 2716. What's left is
1350 * the maximum amount of data we read from a TLS buffer.
1351 */
1352 tls_conf->fragment_size -= 10;
1353
1354 return tls_conf;
1355}
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:474
#define RCSID(id)
Definition build.h:487
#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:383
#define NUM_ELEMENTS(_t)
Definition build.h:339
CONF_ITEM * cf_reference_item(CONF_SECTION const *parent_cs, CONF_SECTION const *outer_cs, char const *ptr)
Definition cf_file.c:3832
#define FR_INTEGER_BOUND_CHECK(_name, _var, _op, _bound)
Definition cf_parse.h:520
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 second identifier of a CONF_SECTION.
Definition cf_util.c:1170
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:1027
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
Definition cf_util.c:683
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:1419
bool cf_item_is_section(CONF_ITEM const *ci)
Determine if CONF_ITEM is a CONF_SECTION.
Definition cf_util.c:617
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
Definition cf_util.c:1574
#define cf_log_err(_cf, _fmt,...)
Definition cf_util.h:288
#define cf_root(_cf)
Definition cf_util.h:98
#define cf_parent(_cf)
Definition cf_util.h:101
#define cf_log_perr(_cf, _fmt,...)
Definition cf_util.h:295
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 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: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: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:3041
VQP attributes.
#define fr_assert(_expr)
Definition rad_assert.h:38
#define REDEBUG(fmt,...)
#define RDEBUG2(fmt,...)
#define RDEBUG(fmt,...)
static bool done
Definition radclient.c:83
static rs_t * conf
Definition radsniff.c:53
#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:560
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:1156
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:937
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
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)
Parse TLS configuration.
Definition tls.c:1288
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:820
unlang_action_t eap_tls_process(request_t *request, eap_session_t *eap_session)
Process an EAP TLS request.
Definition tls.c:982
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